Compare commits
448 Commits
0.1.22_el6
...
master
Author | SHA1 | Date | |
---|---|---|---|
164cd8cb3b | |||
ff4a05ae59 | |||
c1e46207da | |||
f72910cc6b | |||
62b8de1b05 | |||
066f622888 | |||
12c8396be3 | |||
f7835e1b90 | |||
a5ad4081f0 | |||
00790af9bf | |||
55c878cf24 | |||
2cec18b4a5 | |||
1ddf903568 | |||
e5047e7b92 | |||
34d19c8622 | |||
2c29e4ecaa | |||
995bd50151 | |||
7b42d3f2a9 | |||
313e022894 | |||
3159f43ced | |||
b0958e6fba | |||
ed5c8b745f | |||
5acc49a55c | |||
7cfbd64eb4 | |||
221a0afe5d | |||
e0be2c506f | |||
4e50e2b2d4 | |||
f46a580f90 | |||
e0d2825f21 | |||
56fcaf7f6c | |||
5afabbfaad | |||
849170c10b | |||
31ccccd2e0 | |||
1950abbc0f | |||
51fa9f602a | |||
607204a150 | |||
5e7e22d311 | |||
80bfaee714 | |||
8140dcb7cf | |||
820d12a682 | |||
2d88e6fe34 | |||
cd48caa24c | |||
7c42540a66 | |||
a24f4adb81 | |||
a73021a2d5 | |||
8df27d15d7 | |||
cfdd92b9c6 | |||
|
72682f9bad | ||
|
1272a06771 | ||
|
c17260c519 | ||
|
5387ae53b8 | ||
|
415c608252 | ||
|
9ad6d8b1b3 | ||
|
6dc46b819f | ||
|
74b3ba5928 | ||
|
ad9b9b569a | ||
|
0ac983e410 | ||
|
f0e704ce95 | ||
|
1f7b7e86d8 | ||
|
9eb1706e7d | ||
|
02cec2e7e8 | ||
|
6b2c293acd | ||
|
360895affb | ||
|
2c0ea77e90 | ||
|
ca549543c8 | ||
|
4a97f44925 | ||
|
c1f20d9388 | ||
|
0a6c9cdd62 | ||
|
b99e6ca69d | ||
|
5ff7e2214c | ||
|
91ee1f7648 | ||
|
b780d464dd | ||
|
0a32289a83 | ||
|
a0b003c219 | ||
|
b0804d6963 | ||
|
acd74aa1db | ||
|
d0ee0ee54c | ||
|
f40e85abee | ||
|
13e4669fe7 | ||
|
bf190465bf | ||
|
b95cca848c | ||
|
6fbfb70ae0 | ||
|
33c03ebe45 | ||
|
67a3da6404 | ||
|
628f2a5e2e | ||
|
eaad6bd516 | ||
|
1c2c4e8377 | ||
|
4dedf3dc30 | ||
|
089b418416 | ||
|
19ec29e577 | ||
|
2c0eb2e854 | ||
|
7563ab8655 | ||
|
174f9a5cf5 | ||
|
bc0edccfa0 | ||
|
43914cd61d | ||
|
ebfff4b43d | ||
|
8d8c90e31a | ||
|
831b6d9be1 | ||
|
10660aedf6 | ||
|
b2076e496f | ||
|
dd8fe69af8 | ||
|
be7b717c12 | ||
|
ecb831f05a | ||
|
cf1dbfbba0 | ||
|
e8f9e75886 | ||
|
cd790587e6 | ||
|
975e8f1ccc | ||
|
e76a5f4333 | ||
|
9130c512ea | ||
|
6034c7073f | ||
|
c0e1aa14ac | ||
|
cdbbc17ce6 | ||
|
53b83f2d0e | ||
|
78a6b1a2e4 | ||
|
4777b8274f | ||
|
4eb376b929 | ||
|
6467da92c4 | ||
|
31c859df0c | ||
|
ddff2419a2 | ||
|
5bac8a2296 | ||
|
6633658811 | ||
|
4b051b87e8 | ||
|
0b4fa6425c | ||
|
8ac978a1d5 | ||
|
f20de75884 | ||
|
eaf262cb24 | ||
|
40b92cc061 | ||
|
a02b5c780b | ||
|
844c2e3a3e | ||
|
f6b45619ec | ||
|
24ae926c23 | ||
|
b8f7e1ae6d | ||
|
8a22c0bccc | ||
|
ed2884b74f | ||
|
f50e4f34c0 | ||
|
cc9a8bf320 | ||
|
bcf3303f6d | ||
|
bbcef9d0cf | ||
|
a8a6bf8960 | ||
|
a9b2143ae5 | ||
|
c70d1027da | ||
|
0805013d6a | ||
|
4c8ada96a8 | ||
|
f252fabc78 | ||
|
786bbf05ea | ||
|
58ba6e2624 | ||
|
25f165ecc9 | ||
|
c799f083f5 | ||
|
574a37684b | ||
|
3cb67b1b67 | ||
|
661290e473 | ||
|
30a4e4a15d | ||
|
3af623b088 | ||
|
b19b1dfa96 | ||
|
35f1623c5f | ||
|
93ba949e65 | ||
|
4def77e07f | ||
|
b91713591b | ||
|
bceb5a6a4f | ||
|
31a443aa7e | ||
|
493df17e76 | ||
|
eb817e2f7b | ||
|
a38b7ab4b2 | ||
|
0135771c7a | ||
|
376db5167c | ||
|
8180aa2897 | ||
|
7955b547c5 | ||
|
cf4d45c0dc | ||
|
adc4b5dc23 | ||
|
657c2a0ff0 | ||
|
e080780248 | ||
|
058aad1264 | ||
|
8c25777182 | ||
|
f190314a9a | ||
|
d6e5240cf7 | ||
|
7a02253d56 | ||
|
abfa7433e1 | ||
|
7f06d7b2f5 | ||
|
d49e7816d5 | ||
|
7ded61c8af | ||
|
14853e81b4 | ||
|
eb0ada1a69 | ||
|
345cc4d6f3 | ||
|
ca2f76e842 | ||
|
a83b7efb96 | ||
|
810f192184 | ||
|
bcf313009b | ||
|
55642ebede | ||
|
5603e24330 | ||
|
08f7decaf2 | ||
|
ef992661a4 | ||
|
ba0a868fd4 | ||
|
847efa1243 | ||
|
f51a6a930d | ||
|
692517ba87 | ||
|
096253e5dc | ||
|
5be6520118 | ||
|
1b89210fec | ||
|
b108ac7a82 | ||
|
bf787e3670 | ||
|
e30dcda6da | ||
|
db939d3e92 | ||
|
85c1cbc105 | ||
|
772770bfc5 | ||
|
0adedc6b69 | ||
|
05624ee2e1 | ||
|
331090fe0c | ||
|
2251656bfc | ||
|
82a528dfe0 | ||
|
87d6541c89 | ||
|
1775ef9ae3 | ||
|
eef0d74995 | ||
|
4584d988f3 | ||
|
963427dc60 | ||
|
3cee80e348 | ||
|
21fcd4949e | ||
|
020e7a2818 | ||
|
d64a4954cd | ||
|
28d794aba6 | ||
|
36c0a38922 | ||
|
b5315cea86 | ||
|
5493504e77 | ||
|
c7a2c5d8ce | ||
|
2971c73063 | ||
|
dc8bef75ed | ||
|
cd9ee20c02 | ||
|
2a0c6b2ad9 | ||
|
e1090b125b | ||
|
ad7c36b6de | ||
|
ea789a986c | ||
|
f58df33f3b | ||
|
285d61c51c | ||
|
dd98d6d2b6 | ||
|
f4dda266d6 | ||
|
61f56ef30e | ||
|
c9851a2b9d | ||
|
bb9a07d0c0 | ||
|
007b2f5ea5 | ||
|
9383ed9fb0 | ||
|
b275bf549a | ||
|
ec110483dd | ||
|
9de059cdd2 | ||
|
c1b19f1651 | ||
|
e383ffe0fb | ||
|
1c8c99e9c9 | ||
|
a66e9bb827 | ||
|
93e207423a | ||
|
b85a2a653f | ||
|
7f89a211ea | ||
|
6c012aece0 | ||
|
8f69d132e8 | ||
|
a9e468b2e5 | ||
|
8d9a64713c | ||
|
14164177cb | ||
|
2545758742 | ||
|
5e01f9ee2d | ||
|
9668c8eff2 | ||
|
58a1442b67 | ||
|
8cd2c874c7 | ||
|
c3f9b4d919 | ||
|
ca9bab4d12 | ||
|
e51f0065a0 | ||
|
ce3946344f | ||
|
3e464cb4f7 | ||
|
d64fc82d3e | ||
|
b180cd8a27 | ||
|
4a28023967 | ||
|
27af572c34 | ||
|
b32897cc3a | ||
|
36a0844194 | ||
|
26b5624421 | ||
|
02d58e3e53 | ||
|
49f17304ad | ||
|
f85315bb30 | ||
|
d381cb5d31 | ||
|
263253fe87 | ||
|
0a5f2ccce9 | ||
|
93446b2dad | ||
|
3bec374bb2 | ||
|
499a46a8ba | ||
|
54f98a5f27 | ||
|
0862bfa4bc | ||
|
8c062d526c | ||
|
f9504c35e6 | ||
|
d782fc24ab | ||
|
62069067a1 | ||
|
9dfa189fe2 | ||
|
6653922195 | ||
|
ddab13d46b | ||
|
1e9d7a353d | ||
|
ef7dbfa6b6 | ||
|
cf40711197 | ||
|
511ccab917 | ||
|
8f9d165906 | ||
|
2b67439739 | ||
|
f3be79e879 | ||
|
6dc3060f97 | ||
|
a806da0b58 | ||
|
10498eee04 | ||
|
5d12647141 | ||
|
b057750202 | ||
|
21e090cd27 | ||
|
5337376b54 | ||
|
e0b80742cc | ||
|
c793235413 | ||
|
a6ff020641 | ||
|
20a239fb4e | ||
|
ce36e44074 | ||
|
bc4c22dbe5 | ||
|
2c77d2a7c8 | ||
|
dc66533d42 | ||
|
07efb8e1ef | ||
|
e2e617bc89 | ||
|
30b6fdad55 | ||
|
b41cc0b2d6 | ||
|
28b3ec4c26 | ||
|
a991e64c64 | ||
|
3f53c3a0fa | ||
|
d75c9abc81 | ||
|
dc26a547cb | ||
|
bebd1cd6ac | ||
|
7d27a931f3 | ||
|
a7b6a4aaf5 | ||
|
7d882a4778 | ||
|
4556b3e555 | ||
|
8b457ecc69 | ||
|
334a5f1a46 | ||
|
37405cd71d | ||
|
4e94735f0e | ||
|
a5804359db | ||
|
159247fb00 | ||
|
ffe8c6b0a5 | ||
|
c146554291 | ||
|
5d84a64595 | ||
|
a9bc0f7f54 | ||
|
29fe3a445d | ||
|
792943bc0a | ||
|
662d48584e | ||
|
0aef2ec8ab | ||
|
e72efa4415 | ||
|
5db4a536d5 | ||
|
420bb936b3 | ||
|
aa38dad33d | ||
|
65e1f006a7 | ||
|
dec361914d | ||
|
b6c3464cef | ||
|
e28762debd | ||
|
1c610c2b57 | ||
|
d7f456d2ea | ||
|
e409620384 | ||
|
df2da12d82 | ||
|
347ca02674 | ||
|
ce67a8f719 | ||
|
12f723222c | ||
|
0ca02b4974 | ||
|
3a9ec69a56 | ||
|
381db5eb17 | ||
|
cd262c249b | ||
|
b4f79b94e4 | ||
|
0c9fad57bd | ||
|
5b50016e1f | ||
|
f714617bec | ||
|
a548d599bf | ||
|
98c9297292 | ||
|
7b6c8bd1d5 | ||
|
e1a50ab3b0 | ||
|
93bf9cd68d | ||
|
e176f0f799 | ||
|
40efd730f2 | ||
|
f172075029 | ||
|
c465c3e469 | ||
|
6793adbe89 | ||
|
3318a48195 | ||
|
2903b025af | ||
|
6c1bdb43ee | ||
|
a3ecef0f9e | ||
|
282a4abffb | ||
|
0283ab87ec | ||
|
9296ff3b2e | ||
|
6416d60cab | ||
|
c99874dd2d | ||
|
a30233bf33 | ||
|
6c9239a5fd | ||
|
593da4265e | ||
|
ab8ce667b4 | ||
|
6db86ee0c5 | ||
|
9058167a9e | ||
|
c04a3cfcd7 | ||
|
2393ed113e | ||
|
65b6e43f97 | ||
|
68899dc3eb | ||
|
71cf068d67 | ||
|
2ccb17f53c | ||
|
4d03342c5d | ||
|
f8b1f0f4cb | ||
|
91f2db6f71 | ||
|
754f75600a | ||
|
81e5f414c8 | ||
|
0a30e8c9f2 | ||
|
c43bdff1a9 | ||
|
4b73b1f8df | ||
|
f9db23c8c5 | ||
|
f572175a65 | ||
|
2893a84635 | ||
|
7cbbe74685 | ||
|
8747854686 | ||
|
7fd870d984 | ||
|
a6f8585c05 | ||
|
1dbc287840 | ||
|
3183e26efc | ||
|
4975211274 | ||
|
20b5b3aaa6 | ||
|
39038b97c7 | ||
|
c5bf918c51 | ||
|
9a0d53a805 | ||
|
a9cc531768 | ||
|
fc9002b06e | ||
|
c47da02021 | ||
|
33701cc275 | ||
|
f426903cc8 | ||
|
f5a7ebdfed | ||
|
6f52ff1fab | ||
|
6e0872bc3e | ||
|
7b5acdf11e | ||
|
8ba8179fa0 | ||
|
c36585d92d | ||
|
b571fa5509 | ||
|
b9df71e9ba | ||
|
367454e025 | ||
|
cf8585f524 | ||
|
113f72fb3a | ||
|
4094dfc530 | ||
|
c3ee93d817 | ||
|
8e90619012 | ||
|
e7c34c6e58 | ||
|
b2cc891890 | ||
|
fd6de22593 | ||
|
bd4f16e59a | ||
|
da771ec287 | ||
|
0a99008074 | ||
|
310edb5c50 | ||
|
30d1471c2f | ||
|
19d3b616d1 | ||
|
49bb51e27e | ||
|
79dc37ac3a | ||
|
124782c8d6 | ||
|
ba5d5b558e | ||
|
5bb736fac7 |
3
.tito/packages/.readme
Normal file
3
.tito/packages/.readme
Normal file
|
@ -0,0 +1,3 @@
|
|||
the .tito/packages directory contains metadata files
|
||||
named after their packages. Each file has the latest tagged
|
||||
version and the project's relative directory.
|
1
.tito/packages/zabbix-agent-addons
Normal file
1
.tito/packages/zabbix-agent-addons
Normal file
|
@ -0,0 +1 @@
|
|||
0.2.172-1 ./
|
1
.tito/releasers.conf
Symbolic link
1
.tito/releasers.conf
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../tito_libs/releasers.conf
|
6
.tito/tito.props
Normal file
6
.tito/tito.props
Normal file
|
@ -0,0 +1,6 @@
|
|||
[buildconfig]
|
||||
builder = tito.builder.Builder
|
||||
tagger = tito.tagger.VersionTagger
|
||||
changelog_do_not_remove_cherrypick = 0
|
||||
changelog_format = %s (%ae)
|
||||
lib_dir = ../tito_libs
|
|
@ -1,24 +0,0 @@
|
|||
# You can configure here the sensors
|
||||
# Format is <sensors_name>=<command>!<high threshold>!<low threshold>
|
||||
# An alert is triggerd if the temperature is above the high threshold
|
||||
# The alert is cleared if the temperature is less than low threshold
|
||||
# Example:
|
||||
#
|
||||
#
|
||||
## Examples with ipmitool
|
||||
# cpu0 = /usr/bin/ipmitool sdr get 'P1 Therm Margin' | grep 'Sensor Reading' | cut -d':' -f 2 | awk '{print$1}'!-30!-39
|
||||
# mb = /usr/bin/ipmitool sdr get 'Baseboard Temp' | grep 'Sensor Reading' | cut -d':' -f 2 | awk '{print$1}'!50!45
|
||||
#
|
||||
## Examples with smartctl
|
||||
# sda = /usr/sbin/smartctl -a /dev/sda | grep Temperature_Celsius | awk '{print $10}'!45!40
|
||||
# sdb = /usr/sbin/smartctl -a /dev/sdb | grep Temperature_Celsius | awk '{print $10}'!45!50
|
||||
#
|
||||
## Examples with lm_sensors
|
||||
# cpu0=/usr/bin/sensors | grep temp1 | cut -d':' -f 2 | awk '{print $1'} | sed -e "s/+//g" -e "s/.C//g"!65!55
|
||||
#
|
||||
## Examples with acpi
|
||||
# cpu0=cat /proc/acpi/thermal_zone/THRM/temperature | awk '{print $2}'!65!55
|
||||
#
|
||||
#
|
||||
# !!! WARNING !!!
|
||||
# All the commands will be executed with root privileges
|
45
conf/sensors.ini
Normal file
45
conf/sensors.ini
Normal file
|
@ -0,0 +1,45 @@
|
|||
# This file lets you configure which sensors will be monitored by Zabbix
|
||||
# Sensors defined here will be sent to Zabbix through its low level discovery feature
|
||||
# You then have to create discovery rules and prototypes to make use of them
|
||||
#
|
||||
# This file is in ini format, each sensor has its own block and a set of key/value pair
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# [cpu0]
|
||||
# description=Temperature of the first CPU
|
||||
# threshold_high=60
|
||||
# threshold_low=50
|
||||
# cmd="/usr/bin/sensors | grep temp1 | cut -d':' -f 2 | awk '{print $1}' | sed -e 's/+//g' -e 's/.C//g'"
|
||||
# type=temp
|
||||
# unit=°C
|
||||
#
|
||||
# [mb]
|
||||
# description=Motherboard's temperature
|
||||
# threshold_high=50
|
||||
# threshold_low=45
|
||||
# cmd="/usr/bin/ipmitool sdr get 'Baseboard Temp' | grep 'Sensor Reading' | awk '{print $4}'"
|
||||
# type=temp
|
||||
# unit=°C
|
||||
#
|
||||
# [sda]
|
||||
# description=hard drive temperature
|
||||
# threshold_high=50
|
||||
# threshold_low=45
|
||||
# cmd="/usr/sbin/smartctl -A /dev/sda | grep Temperature_Celsius | awk '{print $10}'"
|
||||
# type=temp
|
||||
# unit=°C
|
||||
#
|
||||
# [fan1]
|
||||
# description=front fan
|
||||
# threshold_high=12000
|
||||
# threshold_low=1400
|
||||
# cmd="/usr/bin/ipmitool sdr get 'Fan1A RPM' | grep 'Sensor Reading' | awk '{print $4}'"
|
||||
# type=fan
|
||||
# unit=rpm
|
||||
#
|
||||
#
|
||||
# !!! WARNING !!!
|
||||
# * All the commands will be executed with root privileges
|
||||
# * If your cmd contains quotes, you must double quote the whole command
|
||||
# * If your cmd contains double quotes, you must escape them as \"
|
|
@ -1,2 +1,4 @@
|
|||
Defaults:zabbix !requiretty
|
||||
zabbix ALL=(root) NOPASSWD: /var/lib/zabbix/bin/*_sudo
|
||||
Cmnd_Alias ZABBIX_AGENT = /var/lib/zabbix/bin/*_sudo
|
||||
Defaults!ZABBIX_AGENT !syslog
|
||||
zabbix ALL=(root) NOPASSWD: ZABBIX_AGENT
|
||||
|
|
63
lib/Zabbix/Agent/Addons/Disks.pm
Normal file
63
lib/Zabbix/Agent/Addons/Disks.pm
Normal file
|
@ -0,0 +1,63 @@
|
|||
package Zabbix::Agent::Addons::Disks;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Return an array of block devices, skip if size == 0
|
||||
sub list_block_dev {
|
||||
my @bd = ();
|
||||
opendir(my $dh, "/sys/block") or die "Couldn't open /sys/block: $!";
|
||||
my @blocks = grep { $_ !~ m/^\./ } readdir($dh);
|
||||
closedir($dh);
|
||||
foreach my $block (@blocks){
|
||||
my $size = 1;
|
||||
if ( -e "/sys/block/$block/size"){
|
||||
open SIZE, "/sys/block/$block/size";
|
||||
$size = join "", <SIZE>;
|
||||
close SIZE;
|
||||
chomp($size);
|
||||
next if ($size eq '0');
|
||||
}
|
||||
push @bd, $block;
|
||||
}
|
||||
return @bd;
|
||||
}
|
||||
|
||||
sub list_smart_hdd{
|
||||
my ($param) = shift || {};
|
||||
my @shd = ();
|
||||
if (-x "/usr/sbin/smartctl"){
|
||||
BLOCK: foreach my $block (list_block_dev()){
|
||||
# Skip block we already know won't support SMART
|
||||
next if ($block =~ m/^(ram|loop|md|dm\-)\d+/);
|
||||
my $smart_enabled = 0;
|
||||
my @smart_info = qx(/usr/sbin/smartctl -i /dev/$block);
|
||||
next unless ($? == 0);
|
||||
foreach my $line (@smart_info){
|
||||
if ($line =~ m/^SMART support is:\s+Enabled/i){
|
||||
$smart_enabled = 1;
|
||||
last;
|
||||
} elsif ($line =~ m/NVMe/i){
|
||||
$smart_enabled = 1;
|
||||
last;
|
||||
} elsif ($line =~ m/^Transport protocol:\s+iSCSI/i){
|
||||
# Skip iSCSI block
|
||||
next BLOCK;
|
||||
}
|
||||
}
|
||||
# Skip block unless S.M.A.R.T is advertized as enabled
|
||||
next unless ($smart_enabled);
|
||||
if ($param->{skip_remouvable} && -e "/sys/block/$block/removable"){
|
||||
open REMOVABLE, "/sys/block/$block/removable";
|
||||
my $removable = join "", <REMOVABLE>;
|
||||
close REMOVABLE;
|
||||
chomp($removable);
|
||||
next if ($removable eq '1');
|
||||
}
|
||||
push @shd, $block;
|
||||
}
|
||||
}
|
||||
return @shd;
|
||||
}
|
||||
|
||||
1;
|
917
lib/Zabbix/Agent/Addons/LVM.pm
Normal file
917
lib/Zabbix/Agent/Addons/LVM.pm
Normal file
|
@ -0,0 +1,917 @@
|
|||
package Zabbix::Agent::Addons::LVM;
|
||||
|
||||
# Forked from Linux::LVM
|
||||
# with support for thin pools
|
||||
|
||||
use 5.006;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
# Items to export into callers namespace by default. Note: do not export
|
||||
# names by default without a very good reason. Use EXPORT_OK instead.
|
||||
# Do not simply export all your public functions/methods/constants.
|
||||
|
||||
# This allows declaration use Zabbix::Agent::Addons::LVM ':all';
|
||||
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
||||
# will save memory.
|
||||
our %EXPORT_TAGS = ( 'all' => [ qw( get_volume_group_list
|
||||
get_volume_group_information
|
||||
get_logical_volume_information
|
||||
get_physical_volume_information
|
||||
get_vg_information
|
||||
get_pv_info
|
||||
get_lv_info
|
||||
) ] );
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
|
||||
our @EXPORT = qw( get_volume_group_list
|
||||
get_volume_group_information
|
||||
get_logical_volume_information
|
||||
get_physical_volume_information
|
||||
get_vg_information
|
||||
get_pv_info
|
||||
get_lv_info
|
||||
);
|
||||
|
||||
our $VERSION = '0.18';
|
||||
our $units;
|
||||
|
||||
# Preloaded methods go here.
|
||||
|
||||
# Autoload methods go after =cut, and are processed by the autosplit program.
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: units #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: Set units to be used for pe_size, lv_size, etc. #
|
||||
# legal values are same as lvm --units: #
|
||||
# hbskmgtpeHBSKMGTPE #
|
||||
# (h)uman-readable, (b)ytes, (s)ectors, (k)ilobytes, #
|
||||
# (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes, #
|
||||
# (e)xabytes. Capitalise to use multiples of 1000 (S.I.) #
|
||||
# instead of 1024. #
|
||||
# Can also specify custom units e.g. --units 3M #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: None #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a array with the volume group names. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub units {
|
||||
shift;
|
||||
$units = shift() if @_;
|
||||
return $units;
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_volume_group_list #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a sorted list of all of the #
|
||||
# active volume groups on the system. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: None #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a array with the volume group names. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_volume_group_list() {
|
||||
my %vg = get_vg_information();
|
||||
return (sort keys(%vg));
|
||||
} # End of the get_volume_group_list routine.
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_volume_group_information #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a hash containing all of the #
|
||||
# data about the specified volume group. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: A string containing a volume group name. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a hash with the volume group data. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_volume_group_information($) {
|
||||
my $volume_group = $_[0];
|
||||
my %vg_info;
|
||||
my %vg = get_vg_information();
|
||||
|
||||
foreach(sort keys %{$vg{$volume_group}}) {
|
||||
if ( $_ eq "pvols" ) { next; }
|
||||
elsif( $_ eq "lvols" ) { next; }
|
||||
else {
|
||||
$vg_info{$_} = $vg{$volume_group}->{$_};
|
||||
}
|
||||
}
|
||||
return %vg_info;
|
||||
} # End of the get_volume_group_information routine.
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_volume_group_information #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a hash containing all of the #
|
||||
# data about the specified volume group. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: A string containing a volume group name. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a hash with the volume group data. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_logical_volume_information($) {
|
||||
my $volume_group = $_[0];
|
||||
my %lv_info;
|
||||
my $lvname;
|
||||
my %vg = get_vg_information();
|
||||
|
||||
foreach $lvname (sort keys %{$vg{$volume_group}->{lvols}}) {
|
||||
foreach(sort keys %{$vg{$volume_group}->{lvols}->{$lvname}}) {
|
||||
$lv_info{$lvname}->{$_} = $vg{$volume_group}->{lvols}->{$lvname}->{$_};
|
||||
}
|
||||
}
|
||||
return %lv_info;
|
||||
} # End of the get_logical_volume_information routine.
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_volume_group_information #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a hash containing all of the #
|
||||
# data about the specified volume group. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: A string containing a volume group name. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a hash with the volume group data. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_physical_volume_information($) {
|
||||
my $volume_group = $_[0];
|
||||
my %pv_info;
|
||||
my $pvname;
|
||||
my %vg = get_vg_information();
|
||||
|
||||
foreach $pvname (sort keys %{$vg{$volume_group}->{pvols}}) {
|
||||
foreach(sort keys %{$vg{$volume_group}->{pvols}->{$pvname}}) {
|
||||
$pv_info{$pvname}->{$_} = $vg{$volume_group}->{pvols}->{$pvname}->{$_};
|
||||
}
|
||||
}
|
||||
return %pv_info;
|
||||
} # End of the get_physical_volume_information routine.
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_vg_information #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a hash containing all of the #
|
||||
# volume group information for the system. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: None #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a hash with all of the vg information. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_vg_information() {
|
||||
my %vghash;
|
||||
my $vgn;
|
||||
my $lvn;
|
||||
my $pvn;
|
||||
|
||||
my @vginfo;
|
||||
|
||||
my $units_arg = '';
|
||||
$units_arg = " --units $units " if ($units);
|
||||
if ( -e "/usr/sbin/vgdisplay" ) {
|
||||
@vginfo = `/usr/sbin/vgdisplay -v $units_arg 2>/dev/null`;
|
||||
} else {
|
||||
if( ! -e "/sbin/vgdisplay" ) { die("LVM utilities not installed in /sbin or /usr/sbin"); }
|
||||
@vginfo = `/sbin/vgdisplay -v $units_arg 2>/dev/null`;
|
||||
}
|
||||
|
||||
VGINF: foreach(@vginfo) {
|
||||
chomp;
|
||||
s/^\s+//g;
|
||||
s/\s+$//g;
|
||||
next VGINF if m/^$/;
|
||||
|
||||
# Parse the volume group name.
|
||||
if( m/VG Name\s+(\S+)/ ) {
|
||||
$vgn = $1; $vghash{$vgn}->{vgname} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the volume group access.
|
||||
elsif( m/VG Access\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{access} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the volume group status.
|
||||
elsif( m/VG Status\s+(.+)/ ) {
|
||||
$vghash{$vgn}->{status} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the volume group number.
|
||||
elsif( m/VG #\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{vg_number} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the maximum logical volume size and size unit for the volume group.
|
||||
elsif( m/MAX LV Size\s+(\S+) (\S+)/ ) {
|
||||
$vghash{$vgn}->{max_lv_size} = $1;
|
||||
$vghash{$vgn}->{max_lv_size_unit} = $2;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the maximum number of logical volumes for the volume group.
|
||||
elsif( m/MAX LV\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{max_lv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the current number of logical volumes for the volume group.
|
||||
elsif( m/Cur LV\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{cur_lv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of open logical volumes for the volume group.
|
||||
elsif( m/Open LV\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{open_lv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of physical volumes accessible to the volume group.
|
||||
elsif( m/Max PV\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{max_pv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the current number of physical volumes in the volume group.
|
||||
elsif( m/Cur PV\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{cur_pv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of active physical volumes in the volume group.
|
||||
elsif( m/Act PV\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{act_pv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the size of the volume group.
|
||||
elsif( m/VG Size\s+(\S+) (\S+)/ ) {
|
||||
$vghash{$vgn}->{vg_size} = $1;
|
||||
$vghash{$vgn}->{vg_size_unit} = $2;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the physical extent size and unit for one extent of volume group.
|
||||
elsif( m/PE Size\s+(\S+) (\S+)/ ) {
|
||||
$vghash{$vgn}->{pe_size} = $1;
|
||||
$vghash{$vgn}->{pe_size_unit} = $2;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the total number and number of free physical extents from the physical disk.
|
||||
elsif( m/Total PE \/ Free PE\s+(\S+) \/ (\S+)/m ) {
|
||||
$vghash{$vgn}->{pvols}->{$pvn}->{total_pe} = $1;
|
||||
$vghash{$vgn}->{pvols}->{$pvn}->{free_pe} = $2;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the total number of physical extents from the volume group.
|
||||
elsif( m/Total PE\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{total_pe} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of allocated physical extents from the volume group.
|
||||
elsif( m/Alloc PE \/ Size\s+(\S+) \/ (\S+)(?:\s+(\S+))?/ ) {
|
||||
$vghash{$vgn}->{alloc_pe} = $1;
|
||||
$vghash{$vgn}->{alloc_pe_size} = $2;
|
||||
$vghash{$vgn}->{alloc_pe_size_unit} = $3 || "B";
|
||||
next VGINF; }
|
||||
|
||||
# Parse the volume group name.
|
||||
elsif( m/Free PE \/ Size\s+(\S+) \/ (\S+) (\S+)/ ) {
|
||||
$vghash{$vgn}->{free_pe} = $1;
|
||||
$vghash{$vgn}->{free_pe_size} = $2;
|
||||
$vghash{$vgn}->{free_pe_size_unit} = $3;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the volume group uuid.
|
||||
elsif( m/VG UUID\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{uuid} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the logical volume name.
|
||||
elsif( m/LV Name\s+(\S+)/ ) {
|
||||
$lvn = $1;
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{name} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# since version 2.02.89 'LV Name' is no longer the full path, 'LV Path' is.
|
||||
# LV Path may be bogus or missing in some cases, such as thin pools.
|
||||
if( m/LV Path\s+(\S+)/ ) {
|
||||
$lvn = $1 unless $lvn;
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{name} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the logical volume UUID.
|
||||
elsif( m/LV UUID\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{uuid} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the logical volume UUID.
|
||||
elsif( m/Segments\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{segments} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the logical volume size and unit.
|
||||
elsif( m/LV Size\s+(\S+) (\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{lv_size} = $1;
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{lv_size_unit} = $2;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the logical volume write access.
|
||||
elsif( m/LV Write Access\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{write_access} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the logical volume status.
|
||||
elsif( m/LV Status\s+(.+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{status} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of logical extents in the logical volume.
|
||||
elsif( m/Current LE\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{cur_le} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of allocated logical extents in the logical volume.
|
||||
elsif( m/Allocated LE\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{alloc_le} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the allocation type for the logical volume.
|
||||
elsif( m/Allocation\s+(.+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{allocation} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the volume number.
|
||||
elsif( m/LV #\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{lv_number} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the number of times the logical volume is open.
|
||||
elsif( m/# open\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{open_lv} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the block device of the logical volume.
|
||||
elsif( m/Block device\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{device} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the value for the read ahead sectors of the logical volume.
|
||||
elsif( m/Read ahead sectors\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{read_ahead} = $1;
|
||||
next VGINF; }
|
||||
|
||||
|
||||
elsif( m/Allocated to snapshot\s+(\S+)%/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{'allocated_to_snapshot'} = $1;
|
||||
next VGINF; }
|
||||
|
||||
elsif( m/COW-table size\s+([0-9\.]+)\s+(\S+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{'cow_table_size'} = $1;
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{'cow_table_unit'} = $2;
|
||||
next VGINF; }
|
||||
|
||||
# Thin pools have data and metadata allocations
|
||||
elsif( m/Allocated pool data\s+(\S+)%/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{'allocated_pool_data'} = $1;
|
||||
next VGINF; }
|
||||
|
||||
elsif( m/Allocated metadata\s+(\S+)%/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{'allocated_meta_data'} = $1;
|
||||
next VGINF; }
|
||||
|
||||
elsif( m/Mirrored volumes\s+(.+)/ ) {
|
||||
$vghash{$vgn}->{lvols}->{$lvn}->{'mirrored_volumes'} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the physical disk name.
|
||||
elsif( m/PV Name\s+(\S+)/ ) {
|
||||
$pvn = $1;
|
||||
$vghash{$vgn}->{pvols}->{$pvn}->{device} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the status of the physical disk.
|
||||
elsif( m/PV Status\s+(.+)/ ) {
|
||||
$vghash{$vgn}->{pvols}->{$pvn}->{status} = $1;
|
||||
next VGINF; }
|
||||
|
||||
# Parse the status of the physical disk.
|
||||
elsif( m/PV UUID\s+(.+)/ ) {
|
||||
$vghash{$vgn}->{pvols}->{$pvn}->{uuid} = $1;
|
||||
next VGINF; }
|
||||
|
||||
}
|
||||
return %vghash;
|
||||
} # End of the get_vg_information routine.
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_pv_info #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a hash containing all of the #
|
||||
# information about the specified physical volume. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: None #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a hash with all of the pv information. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_pv_info($) {
|
||||
my $pvname = $_[0];
|
||||
my %pvhash;
|
||||
my @pvinfo;
|
||||
|
||||
if( ! -e "$pvname" ) { die("Physical Disk: $pvname does not exist."); }
|
||||
|
||||
my $units_arg = '';
|
||||
$units_arg = " --units $units " if ($units);
|
||||
|
||||
if ( -e "/usr/sbin/pvdisplay" ) {
|
||||
@pvinfo = `/usr/sbin/pvdisplay $units_arg $pvname`;
|
||||
} else {
|
||||
if( ! -e "/sbin/pvdisplay" ) { die("LVM utilities not installed in /sbin or /usr/sbin"); }
|
||||
@pvinfo = `/sbin/pvdisplay $units_arg $pvname`;
|
||||
}
|
||||
|
||||
|
||||
PVINF: foreach(@pvinfo) {
|
||||
# Get the name of the physical volume.
|
||||
if( m/PV Name\s+(\S+)/ ) {
|
||||
$pvhash{pv_name} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the name of the volume group the physical volume belongs to.
|
||||
if( m/VG Name\s+(\S+)/ ) {
|
||||
$pvhash{vg_name} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the size information of the physical volume.
|
||||
if( m/PV Size\s+(\S+) (\S+)/ ) {
|
||||
$pvhash{size} = $1;
|
||||
$pvhash{size_unit} = $2;
|
||||
next PVINF; }
|
||||
|
||||
# Get the physical volume number.
|
||||
if( m/PV\#\s+(\S+)/ ) {
|
||||
$pvhash{pv_number} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the status of the physical volume.
|
||||
if( m/PV Status\s+(.+)/ ) {
|
||||
$pvhash{status} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the allocation status of the physical volume.
|
||||
if( m/Allocatable\s+(.+)/ ) {
|
||||
$pvhash{allocatable} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the number of logical volumes on the physical volume.
|
||||
if( m/Cur LV\s+(\S+)/ ) {
|
||||
$pvhash{num_lvols} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the physical extent size and unit of the physical volume.
|
||||
if( m/PE Size \((\S+)\)\s+(\S+)/ ) {
|
||||
$pvhash{pe_size} = $2;
|
||||
$pvhash{pe_size_unit} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the total numver of physical extents on the physical volume.
|
||||
if( m/Total PE\s+(\S+)/ ) {
|
||||
$pvhash{total_pe} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the number of free extents on the physical volume.
|
||||
if( m/Free PE\s+(\S+)/ ) {
|
||||
$pvhash{free_pe} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the number of allocated physical extents on the physical volume.
|
||||
if( m/Allocated PE\s+(\S+)/ ) {
|
||||
$pvhash{alloc_pe} = $1;
|
||||
next PVINF; }
|
||||
|
||||
# Get the UUID of the physical volume.
|
||||
if( m/PV UUID\s+(\S+)/ ) {
|
||||
$pvhash{uuid} = $1;
|
||||
next PVINF; }
|
||||
}
|
||||
return %pvhash;
|
||||
} # End of the get_pv_info routine.
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Subroutine: get_lv_info #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Description: This function will return a hash containing all of the #
|
||||
# information about the specified logical volume. #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Parameters: None #
|
||||
#-----------------------------------------------------------------------#
|
||||
# Return Values: On success, a hash with all of the lv information. #
|
||||
#-----------------------------------------------------------------------#
|
||||
sub get_lv_info($) {
|
||||
my $lvname = $_[0];
|
||||
my %lvhash;
|
||||
my @lvinfo;
|
||||
|
||||
my $units_arg = '';
|
||||
$units_arg = " --units $units " if ($units);
|
||||
if ( -e "/usr/sbin/vgdisplay" ) {
|
||||
@lvinfo = `/usr/sbin/lvdisplay $units_arg $lvname`;
|
||||
} else {
|
||||
if( ! -e "/sbin/vgdisplay" ) { die("LVM utilities not installed in /sbin or /usr/sbin"); }
|
||||
@lvinfo = `/sbin/lvdisplay $units_arg $lvname`;
|
||||
}
|
||||
|
||||
LVINF: foreach(@lvinfo) {
|
||||
|
||||
# Get the logical volume name.
|
||||
if( m/LV Name\s+(\S+)/ ) {
|
||||
$lvhash{lv_name} = $1;
|
||||
next LVINF; }
|
||||
|
||||
|
||||
# since version 2.02.89 'LV Name' is no longer the full path, 'LV Path' is.
|
||||
# LV Path may be bogus or missing in some cases, such as thin pools.
|
||||
if( m/LV Path\s+(\S+)/ ) {
|
||||
$lvhash{lv_name} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the volume group name.
|
||||
if( m/VG Name\s+(\S+)/ ) {
|
||||
$lvhash{vg_name} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the volume group name.
|
||||
if( m/LV UUID\s+(\S+)/ ) {
|
||||
$lvhash{uuid} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the logical volume write status.
|
||||
if( m/LV Write Access\s+(.+)/ ) {
|
||||
$lvhash{access} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the logical volume status.
|
||||
if( m/LV Status\s+(.+)/ ) {
|
||||
$lvhash{status} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the logical volume number.
|
||||
if( m/LV \#\s+(\S+)/ ) {
|
||||
$lvhash{lv_number} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the number of opens for the logical volume.
|
||||
if( m/\# open\s+(\S+)/ ) {
|
||||
$lvhash{lv_open} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the logical volume size and size unit.
|
||||
if( m/LV Size\s+(\S+) (\S+)/ ) {
|
||||
$lvhash{size} = $1;
|
||||
$lvhash{size_unit} = $2;
|
||||
next LVINF; }
|
||||
|
||||
# Get the number of extents assigned to the logical volume.
|
||||
if( m/Current LE\s+(\S+)/ ) {
|
||||
$lvhash{current_le} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the number of extents allocated to the logical volume.
|
||||
if( m/Allocated LE\s+(\S+)/ ) {
|
||||
$lvhash{alloc_le} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the extent allocation type of the logical volume.
|
||||
if( m/Allocation\s+(.+)/ ) {
|
||||
$lvhash{allocation} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the number of read ahead sectors for the logical volume.
|
||||
if( m/Read ahead sectors\s+(\S+)/ ) {
|
||||
$lvhash{read_ahead} = $1;
|
||||
next LVINF; }
|
||||
|
||||
# Get the block device of the logical volume.
|
||||
if( m/Block device\s+(\S+)/ ) {
|
||||
$lvhash{block_device} = $1;
|
||||
next LVINF; }
|
||||
|
||||
if( m/Allocated to snapshot\s+(\S+)%/ ) {
|
||||
$lvhash{allocated_to_snapshot} = $1;
|
||||
next LVINF; }
|
||||
|
||||
elsif( m/COW-table size\s+([0-9\.]+)\s+(\S+)/ ) {
|
||||
$lvhash{'cow_table_size'} = $1;
|
||||
$lvhash{'cow_table_unit'} = $2;
|
||||
next LVINF; }
|
||||
|
||||
# Thin pools have data and metadata allocation
|
||||
if( m/Allocated pool data\s+(\S+)%/ ) {
|
||||
$lvhash{allocated_pool_data} = $1;
|
||||
next LVINF; }
|
||||
|
||||
if( m/Allocated metadata\s+(\S+)%/ ) {
|
||||
$lvhash{allocated_meta_data} = $1;
|
||||
next LVINF; }
|
||||
}
|
||||
return %lvhash;
|
||||
} # End of the get_lv_info routine.
|
||||
|
||||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Zabbix::Agent::Addons::LVM - Perl extension for accessing Logical Volume Manager(LVM)
|
||||
data structures on Linux.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Zabbix::Agent::Addons::LVM;
|
||||
Zabbix::Agent::Addons::LVM->units('G');
|
||||
|
||||
=head1 ABSTRACT
|
||||
|
||||
The live data used in the examples is included in the DESCRIPTION area
|
||||
for your convenience and reference.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
units() Get or set the units used to report sizes of LVs, PVs, etc.
|
||||
legal values: hbskmgtpeHBSKMGTPE
|
||||
see man lvm documentation of --units
|
||||
|
||||
get_volume_group_list() This routine will return an array that
|
||||
contains the names of the volume groups.
|
||||
|
||||
@vgs = get_volume_group_list(); print "@vgs \n";
|
||||
Would yield the following: vg00
|
||||
|
||||
|
||||
get_volume_group_information($) This routine will return all of
|
||||
the volume group information about
|
||||
the specified volume group.
|
||||
|
||||
%vg = get_volume_group_information("vg00");
|
||||
foreach(sort keys %vg) {
|
||||
print "$_ = $vg{$_}\n";
|
||||
}
|
||||
Would yield the following:
|
||||
access = read/write
|
||||
act_pv = 2
|
||||
alloc_pe = 3840
|
||||
alloc_pe_size = 15
|
||||
alloc_pe_size_unit = GB
|
||||
cur_lv = 3
|
||||
cur_pv = 2
|
||||
free_pe = 864
|
||||
free_pe_size = 3.38
|
||||
free_pe_size_unit = GB
|
||||
max_lv = 256
|
||||
max_lv_size = 255.99
|
||||
max_lv_size_unit = GB
|
||||
max_pv = 256
|
||||
open_lv = 0
|
||||
pe_size = 4
|
||||
pe_size_unit = MB
|
||||
status = available/resizable
|
||||
total_pe = 4704
|
||||
uuid = BBq8si-NyRR-9ZNW-3J5e-DoRO-RBHK-ckrszi
|
||||
vg_number = 0
|
||||
vg_size = 18.38
|
||||
vg_size_unit = GB
|
||||
vgname = vg00
|
||||
|
||||
|
||||
get_logical_volume_information($) This routine will return all of the
|
||||
logical volume information associated
|
||||
with the specified volume group.
|
||||
|
||||
%lv = get_logical_volume_information("vg00");
|
||||
foreach $lvname (sort keys %lv) {
|
||||
foreach(sort keys %{$lv{$lvname}}) {
|
||||
print "$_ = $lv{$lvname}->{$_}\n";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
Would yield the following results:
|
||||
alloc_le = 1024
|
||||
allocation = next free
|
||||
cur_le = 1024
|
||||
device = 58:0
|
||||
lv_number = 1
|
||||
lv_size = 4
|
||||
lv_size_unit = GB
|
||||
name = /dev/vg00/lvol1
|
||||
open_lv = 0
|
||||
read_ahead = 1024
|
||||
status = available
|
||||
write_access = read/write
|
||||
|
||||
alloc_le = 1280
|
||||
allocation = next free
|
||||
cur_le = 1280
|
||||
device = 58:1
|
||||
lv_number = 2
|
||||
lv_size = 5
|
||||
lv_size_unit = GB
|
||||
name = /dev/vg00/lvol2
|
||||
open_lv = 0
|
||||
read_ahead = 1024
|
||||
status = available
|
||||
write_access = read/write
|
||||
|
||||
alloc_le = 1536
|
||||
allocation = next free
|
||||
cur_le = 1536
|
||||
device = 58:2
|
||||
lv_number = 3
|
||||
lv_size = 6
|
||||
lv_size_unit = GB
|
||||
name = /dev/vg00/lvol3
|
||||
open_lv = 0
|
||||
read_ahead = 1024
|
||||
status = available
|
||||
write_access = read/write
|
||||
|
||||
|
||||
get_physical_volume_information($) This routine will return all of the information
|
||||
information about the physical volumes assigned
|
||||
to the specified volume group.
|
||||
|
||||
%pv = get_physical_volume_information("vg00");
|
||||
foreach $pvname (sort keys %pv) {
|
||||
foreach(sort keys %{$pv{$pvname}}) {
|
||||
print "$_ = $pv{$pvname}->{$_}\n";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
Would yield the following results:
|
||||
device = /dev/hda3
|
||||
free_pe = 0
|
||||
pv_number = 1
|
||||
status = available / allocatable
|
||||
total_pe = 2160
|
||||
|
||||
device = /dev/hda4
|
||||
free_pe = 864
|
||||
pv_number = 2
|
||||
status = available / allocatable
|
||||
total_pe = 2544
|
||||
|
||||
|
||||
get_lv_info($) This routine will return all of the information about the
|
||||
specified logical volume. The information will be returned
|
||||
in a hash.
|
||||
|
||||
get_lv_info
|
||||
%lv = get_lv_info("/dev/vg00/lvol1");
|
||||
foreach (sort keys %lv) {
|
||||
print "$_ = $lv{$_} \n";
|
||||
}
|
||||
Would yield the following results:
|
||||
access = read/write
|
||||
alloc_le = 1024
|
||||
allocation = next free
|
||||
block_device = 58:0
|
||||
current_le = 1024
|
||||
lv_name = /dev/vg00/lvol1
|
||||
lv_number = 1
|
||||
lv_open = 0
|
||||
read_ahead = 1024
|
||||
size = 4
|
||||
size_unit = GB
|
||||
status = available
|
||||
vg_name = vg00
|
||||
|
||||
|
||||
|
||||
get_pv_info($) This routine will return all of the information about the
|
||||
specified physical volume. The information will be returned
|
||||
in a hash.
|
||||
|
||||
%pv = get_pv_info("/dev/hda3");
|
||||
foreach (sort keys %pv) {
|
||||
print "$_ = $pv{$_} \n";
|
||||
}
|
||||
Would yield the following results:
|
||||
alloc_pe = 2160
|
||||
allocatable = yes (but full)
|
||||
free_pe = 0
|
||||
num_lvols = 2
|
||||
pe_size = 4096
|
||||
pe_size_unit = KByte
|
||||
pv_name = /dev/hda3
|
||||
pv_number = 1
|
||||
sectors = 17703630
|
||||
size = 8.44
|
||||
size_info = NOT usable 4.19 MB [LVM: 136 KB]
|
||||
size_unit = GB
|
||||
status = available
|
||||
total_pe = 2160
|
||||
uuid = 2c5ADu-oEdt-ovCe-rqp0-MWpF-I5u1-8XigH4
|
||||
vg_name = vg00
|
||||
|
||||
|
||||
|
||||
Command Output Used In The Above Examples: /sbin/vgdisplay -v
|
||||
--- Volume group ---
|
||||
VG Name vg00
|
||||
VG Access read/write
|
||||
VG Status available/resizable
|
||||
VG # 0
|
||||
MAX LV 256
|
||||
Cur LV 3
|
||||
Open LV 0
|
||||
MAX LV Size 255.99 GB
|
||||
Max PV 256
|
||||
Cur PV 2
|
||||
Act PV 2
|
||||
VG Size 18.38 GB
|
||||
PE Size 4 MB
|
||||
Total PE 4704
|
||||
Alloc PE / Size 3840 / 15 GB
|
||||
Free PE / Size 864 / 3.38 GB
|
||||
VG UUID BBq8si-NyRR-9ZNW-3J5e-DoRO-RBHK-ckrszi
|
||||
|
||||
--- Logical volume ---
|
||||
LV Name /dev/vg00/lvol1
|
||||
VG Name vg00
|
||||
LV Write Access read/write
|
||||
LV Status available
|
||||
LV # 1
|
||||
# open 0
|
||||
LV Size 4 GB
|
||||
Current LE 1024
|
||||
Allocated LE 1024
|
||||
Allocation next free
|
||||
Read ahead sectors 1024
|
||||
Block device 58:0
|
||||
|
||||
--- Logical volume ---
|
||||
LV Name /dev/vg00/lvol2
|
||||
VG Name vg00
|
||||
LV Write Access read/write
|
||||
LV Status available
|
||||
LV # 2
|
||||
# open 0
|
||||
LV Size 5 GB
|
||||
Current LE 1280
|
||||
Allocated LE 1280
|
||||
Allocation next free
|
||||
Read ahead sectors 1024
|
||||
Block device 58:1
|
||||
|
||||
--- Logical volume ---
|
||||
LV Name /dev/vg00/lvol3
|
||||
VG Name vg00
|
||||
LV Write Access read/write
|
||||
LV Status available
|
||||
LV # 3
|
||||
# open 0
|
||||
LV Size 6 GB
|
||||
Current LE 1536
|
||||
Allocated LE 1536
|
||||
Allocation next free
|
||||
Read ahead sectors 1024
|
||||
Block device 58:2
|
||||
|
||||
--- Physical volumes ---
|
||||
PV Name (#) /dev/hda3 (1)
|
||||
PV Status available / allocatable
|
||||
Total PE / Free PE 2160 / 0
|
||||
|
||||
PV Name (#) /dev/hda4 (2)
|
||||
PV Status available / allocatable
|
||||
Total PE / Free PE 2544 / 864
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<vgdisplay>(1M)
|
||||
L<lvdisplay>(1M)
|
||||
L<pvdisplay>(1M)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chad Kerner, E<lt>chadkerner@yahoo.comE<gt>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright 2003 by Chad Kerner
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
Modified by Daniel Berteaud <daniel@firewall-services.com> to add
|
||||
support for LVM thin
|
||||
|
||||
=cut
|
21
lib/Zabbix/Agent/Addons/UPS.pm
Normal file
21
lib/Zabbix/Agent/Addons/UPS.pm
Normal file
|
@ -0,0 +1,21 @@
|
|||
package Zabbix::Agent::Addons::UPS;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use File::Which;
|
||||
|
||||
# List configured UPS (only nut is supported)
|
||||
sub list_ups {
|
||||
my @ups = ();
|
||||
my $upsc = which('upsc');
|
||||
if ($upsc && -x $upsc){
|
||||
my @out = qx($upsc -l 2>/dev/null);
|
||||
if ($? == 0){
|
||||
@ups = @out;
|
||||
chomp @ups;
|
||||
}
|
||||
}
|
||||
return @ups;
|
||||
};
|
||||
|
||||
1;
|
27
selinux/zabbix-agent-addons.te
Normal file
27
selinux/zabbix-agent-addons.te
Normal file
|
@ -0,0 +1,27 @@
|
|||
module zabbix-agent-addons 1.0;
|
||||
|
||||
require {
|
||||
type kernel_t;
|
||||
type devlog_t;
|
||||
type zabbix_var_lib_t;
|
||||
type sudo_exec_t;
|
||||
type proc_mdstat_t;
|
||||
type zabbix_agent_t;
|
||||
class process setrlimit;
|
||||
class capability { audit_write dac_override sys_resource };
|
||||
class file { execute execute_no_trans getattr ioctl open read };
|
||||
class netlink_audit_socket { create nlmsg_relay };
|
||||
class sock_file write;
|
||||
class unix_dgram_socket { connect create sendto };
|
||||
}
|
||||
|
||||
#============= zabbix_agent_t ==============
|
||||
allow zabbix_agent_t devlog_t:sock_file write;
|
||||
allow zabbix_agent_t kernel_t:unix_dgram_socket sendto;
|
||||
allow zabbix_agent_t proc_mdstat_t:file { getattr ioctl open read };
|
||||
allow zabbix_agent_t self:capability { audit_write dac_override sys_resource };
|
||||
allow zabbix_agent_t self:netlink_audit_socket { create nlmsg_relay };
|
||||
allow zabbix_agent_t self:process setrlimit;
|
||||
allow zabbix_agent_t self:unix_dgram_socket { connect create };
|
||||
allow zabbix_agent_t sudo_exec_t:file { execute execute_no_trans };
|
||||
allow zabbix_agent_t zabbix_var_lib_t:file { execute execute_no_trans ioctl open read };
|
|
@ -1,7 +1,11 @@
|
|||
%if 0%{?rhel} && 0%{?rhel} < 7
|
||||
%global _without_selinux 1
|
||||
%endif
|
||||
|
||||
Summary: Scripts for Zabbix monitoring
|
||||
Name: zabbix-agent-addons
|
||||
Version: 0.1.21
|
||||
Release: 1
|
||||
Version: 0.2.172
|
||||
Release: 1%{?dist}
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
BuildArch: noarch
|
||||
|
||||
|
@ -13,10 +17,22 @@ Requires: zabbix-agent
|
|||
Requires: perl(Getopt::Long)
|
||||
Requires: perl(Getopt::Std)
|
||||
Requires: perl(JSON)
|
||||
Requires: perl(Linux::LVM)
|
||||
Requires: perl(POSIX)
|
||||
Requires: perl(MIME::Base64)
|
||||
Requires: perl(File::Which)
|
||||
Requires: perl(Config::Simple)
|
||||
Requires: perl(Statistics::Descriptive)
|
||||
%if 0%{?rhel} > 6
|
||||
# used by samba4 scripts, which wont run on anything < 7
|
||||
Requires: perl(File::ReadBackwards)
|
||||
%endif
|
||||
Requires: fping
|
||||
BuildRequires: perl
|
||||
%if ! 0%{?_without_selinux}
|
||||
Requires: policycoreutils
|
||||
BuildRequires: selinux-policy-devel
|
||||
BuildRequires: checkpolicy
|
||||
%endif
|
||||
|
||||
AutoReqProv: no
|
||||
|
||||
|
@ -30,6 +46,11 @@ LVM, RAID status, S.M.A.R.T. drives, BackupPC etc...
|
|||
%setup -q
|
||||
|
||||
%build
|
||||
%if ! 0%{?_without_selinux}
|
||||
pushd selinux
|
||||
make -f %{_datadir}/selinux/devel/Makefile
|
||||
popd
|
||||
%endif
|
||||
|
||||
%install
|
||||
|
||||
|
@ -41,31 +62,711 @@ LVM, RAID status, S.M.A.R.T. drives, BackupPC etc...
|
|||
# Install Zabbix conf
|
||||
%{__install} -d $RPM_BUILD_ROOT%{_sysconfdir}/zabbix/zabbix_agentd.conf.d/
|
||||
%{__install} -m 0644 zabbix_conf/* $RPM_BUILD_ROOT%{_sysconfdir}/zabbix/zabbix_agentd.conf.d/
|
||||
# Install perl modules
|
||||
%{__install} -d -m 0755 $RPM_BUILD_ROOT%{perl_vendorlib}
|
||||
cp -r lib/* $RPM_BUILD_ROOT%{perl_vendorlib}/
|
||||
# Install sensors conf
|
||||
%{__install} -m 0755 conf/sensors.conf $RPM_BUILD_ROOT%{_sysconfdir}/zabbix/
|
||||
%{__install} -m 0755 conf/sensors.ini $RPM_BUILD_ROOT%{_sysconfdir}/zabbix/
|
||||
# Install sudo conf
|
||||
%{__install} -d 750 $RPM_BUILD_ROOT%{_sysconfdir}/sudoers.d
|
||||
%{__install} -m 600 conf/sudo.conf $RPM_BUILD_ROOT%{_sysconfdir}/sudoers.d/zabbix_agent
|
||||
# Install SELinux policy
|
||||
%if ! 0%{?_without_selinux}
|
||||
%{__install} -d 750 $RPM_BUILD_ROOT%{_datadir}/selinux/packages/%{name}
|
||||
%{__install} -m644 selinux/%{name}.pp $RPM_BUILD_ROOT%{_datadir}/selinux/packages/%{name}/%{name}.pp
|
||||
%endif
|
||||
|
||||
%clean
|
||||
%{__rm} -rf $RPM_BUILD_ROOT
|
||||
|
||||
%pre
|
||||
|
||||
|
||||
%preun
|
||||
|
||||
%post
|
||||
if [ $1 -eq 2 ] ; then
|
||||
if [ -e "/etc/zabbix/sensors.conf" ]; then
|
||||
/var/lib/zabbix/bin/util_convert_sensors_ini /etc/zabbix/sensors.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc README CHANGELOG.git
|
||||
%doc README
|
||||
%doc zabbix_templates/*
|
||||
%dir %attr(0750,zabbix,zabbix) %{_localstatedir}/lib/zabbix/bin
|
||||
%{_localstatedir}/lib/zabbix/bin/*
|
||||
%config(noreplace) %attr(0640,root,zabbix) %{_sysconfdir}/zabbix/sensors.conf
|
||||
%{perl_vendorlib}
|
||||
%config(noreplace) %attr(0640,root,zabbix) %{_sysconfdir}/zabbix/sensors.ini
|
||||
%config(noreplace) %attr(0640,root,zabbix) %{_sysconfdir}/zabbix/zabbix_agentd.conf.d/*
|
||||
%attr(0440,root,root) %{_sysconfdir}/sudoers.d/*
|
||||
%if ! 0%{?_without_selinux}
|
||||
%{_datadir}/selinux/packages/%{name}/%{name}.pp
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Dec 21 2023 Daniel Berteaud <dbd@ehtrace.com> 0.2.172-1
|
||||
- Add Zabbix template for storageDevices (dbd@ehtrace.com)
|
||||
- Read raw value for SSL_Life_Left (dbd@ehtrace.com)
|
||||
- Read SSD_Life_Left if available (dbd@ehtrace.com)
|
||||
- /dev/bus/0 might not exist but can be queried (dbd@ehtrace.com)
|
||||
- Report more info from some NVMe (dbd@ehtrace.com)
|
||||
- Adjust default values for stor dev (dbd@ehtrace.com)
|
||||
- Fix UserParam (dbd@ehtrace.com)
|
||||
- Add new script for smart monitoring (dbd@ehtrace.com)
|
||||
|
||||
* Tue Sep 19 2023 Daniel Berteaud <dbd@ehtrace.com> 0.2.171-1
|
||||
- Ignore samba NT_STATUS_PROTOCOL_UNREACHABLE errors (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jun 29 2023 Daniel Berteaud <dbd@ehtrace.com> 0.2.170-1
|
||||
- Fix + discover NMVe (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jun 29 2023 Daniel Berteaud <dbd@ehtrace.com> 0.2.169-1
|
||||
- Better sensor output parsing (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jun 29 2023 Daniel Berteaud <dbd@ehtrace.com> 0.2.168-1
|
||||
- Drop ipmitool stderr and simplify output parsing (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jun 29 2023 Daniel Berteaud <dbd@ehtrace.com> 0.2.167-1
|
||||
- Fix fan detection on some BMC boards (dbd@ehtrace.com)
|
||||
- Update ZFS template (dbd@ehtrace.com)
|
||||
|
||||
* Sat Mar 26 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.166-1
|
||||
- Fix counting samba computers auth tries (dbd@ehtrace.com)
|
||||
|
||||
* Mon Mar 21 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.165-1
|
||||
- last_seen might not be defined in check_unifi (dbd@ehtrace.com)
|
||||
|
||||
* Mon Mar 21 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.164-1
|
||||
- Use JSON bool in unifi scripts (dbd@ehtrace.com)
|
||||
|
||||
* Mon Jan 24 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.163-1
|
||||
- Fix check_zimbra_sudo (dbd@ehtrace.com)
|
||||
|
||||
* Fri Jan 21 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.162-1
|
||||
- Add alloc_ct for LVM VG when missing (dbd@ehtrace.com)
|
||||
|
||||
* Fri Jan 21 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.161-1
|
||||
- Fix Zimbra discovery and check scripts (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jan 20 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.160-1
|
||||
- Add a {#DOCKER_CONTAINER_STATUS} LLD macro (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jan 20 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.159-1
|
||||
- Update Docker template (dbd@ehtrace.com)
|
||||
- Don't query state in docker discovery (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jan 13 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.158-1
|
||||
- Small fixes for Docker check script and template (dbd@ehtrace.com)
|
||||
|
||||
* Thu Jan 13 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.157-1
|
||||
- Enhacements in the Docker template (dbd@ehtrace.com)
|
||||
|
||||
* Wed Jan 12 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.156-1
|
||||
- Add Docker scripts (dbd@ehtrace.com)
|
||||
|
||||
* Tue Jan 11 2022 Daniel Berteaud <dbd@ehtrace.com> 0.2.155-1
|
||||
- Release bump
|
||||
|
||||
* Thu Dec 16 2021 Daniel Berteaud <dani@lapiole.org> 0.2.154-1
|
||||
- Fix zpool iostat as /proc/spl/kstat/zfs/pool/io doesn't exist anymore
|
||||
(dani@lapiole.org)
|
||||
- Add nodata triggers for Elasticsearch (daniel@firewall-services.com)
|
||||
- Include Zabbix template for Elasticsearch (daniel@firewall-services.com)
|
||||
|
||||
* Tue Oct 19 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.153-1
|
||||
- Tweak elasticsearch monitoring scripts (daniel@firewall-services.com)
|
||||
|
||||
* Mon Oct 18 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.152-1
|
||||
- Small fixes in elasticsearch scripts (daniel@firewall-services.com)
|
||||
|
||||
* Mon Oct 18 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.151-1
|
||||
- Add Elasticsearch monitoring scripts (daniel@firewall-services.com)
|
||||
- Updates and fixes in Zabbix templates (daniel@firewall-services.com)
|
||||
|
||||
* Fri Jul 16 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.150-1
|
||||
- Do not count Unconfigured(good) drives as an error (daniel@firewall-
|
||||
services.com)
|
||||
- Remove duplicated templates (daniel@firewall-services.com)
|
||||
- Typo in template filename (daniel@firewall-services.com)
|
||||
- Update and provide more templates (daniel@firewall-services.com)
|
||||
- Update and add more Zabbix templates (daniel@firewall-services.com)
|
||||
- Remove health and capacity sanoid checks from discovery (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Thu May 27 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.149-1
|
||||
- Support Debian lib path for BackupPC (daniel@firewall-services.com)
|
||||
|
||||
* Wed Feb 17 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.148-1
|
||||
- Fix zfs pool monitoring when a pool has errors (daniel@firewall-services.com)
|
||||
- Alert only if not samba monitoring for 25min (instead of 15)
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Thu Jan 14 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.147-1
|
||||
- [check_samba_dc_sudo] Fix typo with GPO listing (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Thu Jan 14 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.146-1
|
||||
- [check_samba_sudo] Update default audit log file path, and drop errors from
|
||||
samba-tool (daniel@firewall-services.com)
|
||||
|
||||
* Thu Jan 14 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.145-1
|
||||
- Add perl(File::ReadBackwards) dependency (daniel@firewall-services.com)
|
||||
|
||||
* Thu Jan 14 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.144-1
|
||||
- Optimize samba audit_auth log parsing by reading from the tail of the file
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Wed Jan 13 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.143-1
|
||||
- Update BackupPC template (daniel@firewall-services.com)
|
||||
|
||||
* Wed Jan 13 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.142-1
|
||||
- Modernize lvm monitoring scripts (daniel@firewall-services.com)
|
||||
- Don't catch stderr for vgdisplay commands (daniel@firewall-services.com)
|
||||
|
||||
* Tue Jan 12 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.141-1
|
||||
- Small fixes in check_samba_dc (skip unparsable logs, and handle message with
|
||||
NT_STATUS_NO_SUCH_USER (daniel@firewall-services.com)
|
||||
|
||||
* Mon Jan 11 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.140-1
|
||||
- Add general stats to BackupPC monitoring script (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Mon Jan 11 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.139-1
|
||||
- Add OU discovery to samba monitoring (daniel@firewall-services.com)
|
||||
|
||||
* Mon Jan 11 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.138-1
|
||||
- Add missing Samba application name for aggregated items (daniel@firewall-
|
||||
services.com)
|
||||
- Minor fixes for samba script and template (daniel@firewall-services.com)
|
||||
|
||||
* Sat Jan 09 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.137-1
|
||||
- Add scripts and template to monitor Samba 4 DC (daniel@firewall-services.com)
|
||||
|
||||
* Fri Jan 08 2021 Daniel Berteaud <daniel@firewall-services.com> 0.2.136-1
|
||||
- Add guest counter for PVE cluster and node (daniel@firewall-services.com)
|
||||
|
||||
* Thu Dec 17 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.135-1
|
||||
- Update Template_App_MySQL (daniel@firewall-services.com)
|
||||
- Update Template_App_ZFS (daniel@firewall-services.com)
|
||||
|
||||
* Tue Dec 01 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.134-1
|
||||
- Possibility to check certificate for Unifi API (daniel@firewall-services.com)
|
||||
|
||||
* Sat Nov 07 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.133-1
|
||||
- Add perl in BuildReq for el8 (daniel@firewall-services.com)
|
||||
|
||||
* Mon Oct 26 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.132-1
|
||||
- Run upsc commands with 2>/de/null (daniel@firewall-services.com)
|
||||
- IPMI sensors can have / and - in their name (daniel@firewall-services.com)
|
||||
|
||||
* Thu Oct 22 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.131-1
|
||||
- Don't return garbage in mpath discovery if command failed (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Tue Oct 20 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.130-1
|
||||
- Add App_Multipath template (daniel@firewall-services.com)
|
||||
- Add Linux_Server template (daniel@firewall-services.com)
|
||||
|
||||
* Tue Oct 20 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.129-1
|
||||
- Add scripts to discover and check multipath devices (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Tue Sep 29 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.128-1
|
||||
- Use MAC of device if no name is defined in Unifi device discovery
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Wed Sep 23 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.127-1
|
||||
- Update scripts to work with ssacli (in adition to hpacucli) (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Fri Sep 04 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.126-1
|
||||
- Add some compatibility for older MySQL servers (daniel@firewall-services.com)
|
||||
|
||||
* Tue Sep 01 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.125-1
|
||||
- Allow empty --defaults opt for check_mysql_sudo (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Mon Aug 31 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.124-1
|
||||
- Update Template_App_MySQL (daniel@firewall-services.com)
|
||||
|
||||
* Mon Aug 31 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.123-1
|
||||
- check_mysql needs sudo permissions (daniel@firewall-services.com)
|
||||
|
||||
* Mon Aug 31 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.122-1
|
||||
- Add MySQL monitoring script and template (daniel@firewall-services.com)
|
||||
- Add Template_Vhost (daniel@firewall-services.com)
|
||||
- Add templates for Windows (minimal and server) (daniel@firewall-services.com)
|
||||
- Add /usr/local/BackupPC/lib as lib dir for BackupPC scripts (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Wed May 20 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.121-1
|
||||
- Do not rely on distrib version to check if --output-format is needed for
|
||||
check_pve_sudo (daniel@firewall-services.com)
|
||||
|
||||
* Fri Apr 03 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.120-1
|
||||
- Fix mdadm when we have spares (daniel@firewall-services.com)
|
||||
|
||||
* Tue Mar 03 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.119-1
|
||||
- Better detection of smart capable drives (daniel@firewall-services.com)
|
||||
|
||||
* Mon Mar 02 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.118-1
|
||||
- Update Template_App_PVE_Cluster (daniel@firewall-services.com)
|
||||
|
||||
* Mon Mar 02 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.117-1
|
||||
- Add basic SNMP templates (daniel@firewall-services.com)
|
||||
- Add Template_App_Unifi (daniel@firewall-services.com)
|
||||
- Add Template_OS_PfSense2 (daniel@firewall-services.com)
|
||||
- Add Template_Ping (daniel@firewall-services.com)
|
||||
- Fix cache when the same resource is queried with different options
|
||||
(daniel@firewall-services.com)
|
||||
- Remove debug statement in util_populate_pve_cache (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Mon Mar 02 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.116-1
|
||||
- Default to accept cached value up to 5 min old for check_pve_sudo
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Mon Mar 02 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.115-1
|
||||
- Add a script to populate check_pve_sudo cache (daniel@firewall-services.com)
|
||||
- Enhance check_pve_sudo with a local cache support to speed up monitoring
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Tue Feb 25 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.114-1
|
||||
- Automatic commit of package [zabbix-agent-addons] release [0.2.112-1].
|
||||
(daniel@firewall-services.com)
|
||||
- drop stderrr for upsc commands (daniel@firewall-services.com)
|
||||
|
||||
* Tue Feb 25 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.113-1
|
||||
- Skip Core X temp sensors (daniel@firewall-services.com)
|
||||
|
||||
* Wed Feb 19 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.112-1
|
||||
- drop stderrr for upsc commands (daniel@firewall-services.com)
|
||||
|
||||
* Mon Feb 17 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.111-1
|
||||
- Update ZFS and BackupPC templates (daniel@firewall-services.com)
|
||||
|
||||
* Mon Feb 10 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.110-1
|
||||
- Fix a typo in ZabbixSizeTooSmallFactor conf (daniel@firewall-services.com)
|
||||
|
||||
* Wed Feb 05 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.109-1
|
||||
- Don't skip local node in PVE nodes discovery (daniel@firewall-services.com)
|
||||
|
||||
* Wed Jan 22 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.108-1
|
||||
- Only skip RAID volumes checks when in HBA mode, not physical disks checks
|
||||
(daniel@firewall-services.com)
|
||||
- Declar variable in the correct scope for hba mode detection (daniel@firewall-
|
||||
services.com)
|
||||
- Handle megaraid controlers in HBO/JBOD mode (skip RAID checks)
|
||||
(daniel@firewall-services.com)
|
||||
- Use head -1 to be sure to get a single value for sensors (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Thu Jan 16 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.107-1
|
||||
- Add Zabbix template for Squid (daniel@firewall-services.com)
|
||||
|
||||
* Thu Jan 16 2020 Daniel Berteaud <daniel@firewall-services.com> 0.2.106-1
|
||||
- Remove uri from UsereParam args for squid (daniel@firewall-services.com)
|
||||
|
||||
* Tue Dec 17 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.105-1
|
||||
- Fix ready sizeNew from last backup (except when link hasn't ran yet)
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 15 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.104-1
|
||||
- Disable vfs.dev.discovery in default conf (daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 15 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.103-1
|
||||
- Set min backup size to 0 in template (daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 15 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.102-1
|
||||
- Fix key name for enabled value (daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 15 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.101-1
|
||||
- Init complete JSON objects with default values in bheck_backuppc_sudo
|
||||
(daniel@firewall-services.com)
|
||||
- Remove unused variables (daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 15 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.100-1
|
||||
- Only substract $new_size_of_last_full once (daniel@firewall-services.com)
|
||||
|
||||
* Fri Dec 13 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.99-1
|
||||
- Fix when a host has a single backup with 0 new file size (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Fri Dec 13 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.98-1
|
||||
- Fix backups total size computation when there's only one full
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Fri Dec 13 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.97-1
|
||||
- Include Zabbix template to monitor BackupPC (daniel@firewall-services.com)
|
||||
|
||||
* Fri Dec 13 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.96-1
|
||||
- Enhanced stats for BackupPC's entity (daniel@firewall-services.com)
|
||||
|
||||
* Wed Dec 11 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.95-1
|
||||
- Wait for BackupPC_link to run before we take new sizes in our stat
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Wed Dec 11 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.94-1
|
||||
- Fix BackupPC script when BackuPPC_link is waiting for the nightly cleanup to
|
||||
finish (daniel@firewall-services.com)
|
||||
|
||||
* Fri Nov 29 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.93-1
|
||||
- Don't use autoloader in our forked Linux::LVM (daniel@firewall-services.com)
|
||||
- Don't requires Linux::LVM anymore (daniel@firewall-services.com)
|
||||
- Replace Linux::LVM occurrences with Zabbix::Agent::Addons::LVM
|
||||
(daniel@firewall-services.com)
|
||||
- Bundle a fork of Linux::LVM with support for LVM thin pools (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Wed Nov 27 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.92-1
|
||||
- Better compat with 4.4 vfs.dev.discovery (and use lsblk to get the list of
|
||||
dev if available) (daniel@firewall-services.com)
|
||||
|
||||
* Tue Nov 26 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.91-1
|
||||
- Add DEVNAME macro for vfs.dev.discovery to ease transition to 4.4
|
||||
(daniel@firewall-services.com)
|
||||
- Minor update in ZFS template (daniel@firewall-services.com)
|
||||
|
||||
* Sun Oct 20 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.90-1
|
||||
- Fix some unifi stats for uap/usw in recent unifi versions (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Mon Oct 14 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.89-1
|
||||
- Add Zabbix template for GlusterFS (daniel@firewall-services.com)
|
||||
- Add Zabbix tempalte for DRBD (daniel@firewall-services.com)
|
||||
- Add Zabbix template for Proxmox Mail Gateway (daniel@firewall-services.com)
|
||||
- Add template to monitor a PVE cluster (daniel@firewall-services.com)
|
||||
- ZFS ARC low hit ratio for data and global are calculated for 1h
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Fri Oct 11 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.88-1
|
||||
- Add Zabbix template for ZFS (daniel@firewall-services.com)
|
||||
|
||||
* Fri Oct 11 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.87-1
|
||||
- Enhance ZFS monitoring scripts to retrieve ARC stats (daniel@firewall-
|
||||
services.com)
|
||||
- Send an empty data array when Zimbra is not installed (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Tue Oct 01 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.86-1
|
||||
- Fix pve script when no net or disk stats are available (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Sat Sep 21 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.85-1
|
||||
- Check $sanoidmon is defined before checking its value (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Sat Sep 21 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.84-1
|
||||
- Fix var name in disco_zfs (daniel@firewall-services.com)
|
||||
|
||||
* Sat Sep 21 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.83-1
|
||||
- Better sanoïd monitoring integration (daniel@firewall-services.com)
|
||||
|
||||
* Fri Sep 20 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.82-1
|
||||
- Remove trailing x for compressratio with ZoL < 0.8 (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Fri Sep 20 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.81-1
|
||||
- Revert to suffix conversion for ZFS error count (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Fri Sep 20 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.80-1
|
||||
- Rewrite ZFS monitoring from scratch (daniel@firewall-services.com)
|
||||
- Set info in the data element for Zimbra discovery (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Fri Sep 13 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.79-1
|
||||
- Add simple Zabbix service status scripts (daniel@firewall-services.com)
|
||||
|
||||
* Tue Sep 03 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.77-1
|
||||
- Skip self PVE node (daniel@firewall-services.com)
|
||||
|
||||
* Tue Jul 30 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.76-1
|
||||
- Add support for some NVMe temp sensors Found on OVH's Advanced servers for
|
||||
example (daniel@firewall-services.com)
|
||||
- Fix when running on Debian buster Which fails with RC 25 when using
|
||||
File::Spec devnull (daniel@firewall-services.com)
|
||||
|
||||
* Tue May 21 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.75-1
|
||||
- Add basic scripts to monitor VDO volumes (daniel@firewall-services.com)
|
||||
|
||||
* Tue Apr 16 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.74-1
|
||||
- Don't fail if Statistics::Descriptive doesn't support quantile
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Mon Apr 15 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.73-1
|
||||
- More work on BackupPC's monitoring scripts (daniel@firewall-services.com)
|
||||
|
||||
* Thu Apr 04 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.72-1
|
||||
- Fix reporting MaxXferError (daniel@firewall-services.com)
|
||||
|
||||
* Thu Apr 04 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.71-1
|
||||
- Fix a typo in check_backuppc_sudo (daniel@firewall-services.com)
|
||||
|
||||
* Thu Apr 04 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.70-1
|
||||
- Fix counting entity size (daniel@firewall-services.com)
|
||||
|
||||
* Thu Apr 04 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.69-1
|
||||
- Don't count vm as an entity in BackupPC's entities discovery
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Thu Apr 04 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.68-1
|
||||
- Update BackupPC's discovery and monitoring scripts (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Wed Apr 03 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.67-1
|
||||
- Add last_errors in backuppc JSON info (daniel@firewall-services.com)
|
||||
- Update conf for BackupPC (daniel@firewall-services.com)
|
||||
|
||||
* Wed Apr 03 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.66-1
|
||||
- Remove crazy and useless regex to exclude hosts from BackupPC
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Wed Apr 03 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.65-1
|
||||
- Enhance backuppc reporting script Including reporting the new file size, and
|
||||
sending all the info at once in JSON format (daniel@firewall-services.com)
|
||||
- Some coding style updates (daniel@firewall-services.com)
|
||||
- More compact BPCSTATUS (1/0 instead of enabled/disabled) (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Wed Feb 20 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.64-1
|
||||
- Also report the number in the deferred queue (daniel@firewall-services.com)
|
||||
|
||||
* Wed Feb 20 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.63-1
|
||||
- Report number of email in the active and hold queues (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Sat Jan 19 2019 Daniel Berteaud <daniel@firewall-services.com> 0.2.62-1
|
||||
- Add scripts to ping other hosts (daniel@firewall-services.com)
|
||||
|
||||
* Mon Dec 10 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.61-1
|
||||
- Save cookies to a file so we don't have to login at every invocation GLPI
|
||||
#34449 (daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 09 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.60-1
|
||||
- Print ZBX_NOTSUPPORTED in case of API error Prevent tons of error messages in
|
||||
Zabbix Server's logs (daniel@firewall-services.com)
|
||||
|
||||
* Sun Dec 09 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.59-1
|
||||
- Fix ZBX_NOTSUPPORTED string in several scripts (daniel@firewall-services.com)
|
||||
|
||||
* Thu Nov 15 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.57-0.beta1
|
||||
- Add enhanced squid monitoring support (daniel@firewall-services.com)
|
||||
|
||||
* Fri Nov 09 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.56-1
|
||||
- Add simple script for nginx (similar httpd) (daniel@firewall-services.com)
|
||||
|
||||
* Fri Oct 26 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.55-1
|
||||
- Fix PVE storage monitoring GLPI #33910 (daniel@firewall-services.com)
|
||||
|
||||
* Wed Oct 24 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.54-1
|
||||
- Rework PMG monitoring scripts (daniel@firewall-services.com)
|
||||
|
||||
* Thu Oct 18 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.52-0.beta1
|
||||
- Add very basic script for PMG monitoring (daniel@firewall-services.com)
|
||||
|
||||
* Tue Sep 18 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.51-1
|
||||
- check_unifi: also output satisfaction for stations (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Mon Sep 17 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.50-1
|
||||
- Fix comparison with uninitialized value in check_unifi (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Sat Sep 15 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.49-1
|
||||
- Report number of unarchived alarms in check_unifi --unifi (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Sat Sep 15 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.48-1
|
||||
- More fixes for AP monitoring in check_unifi (daniel@firewall-services.com)
|
||||
|
||||
* Sat Sep 15 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.47-1
|
||||
- Several fixes in check_unifi (daniel@firewall-services.com)
|
||||
|
||||
* Fri Sep 14 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.46-1
|
||||
- Enhance Unifi discovery and monitoring Adding support for station monitoring
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Thu Sep 13 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.45-0.beta2
|
||||
- Fix check_unifi when value is defined but false (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Thu Sep 13 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.44-0.beta1
|
||||
- Add scripts to monitor Unifi sites (daniel@firewall-services.com)
|
||||
|
||||
* Tue Aug 21 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.43-1
|
||||
- Fix PVE scripts to Work with new pvesh version (daniel@firewall-services.com)
|
||||
|
||||
* Mon Jul 23 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.42-1
|
||||
- Initialize an empty json object (daniel@firewall-services.com)
|
||||
|
||||
* Mon Jul 09 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.41-1
|
||||
- Don't log sudo usage for Zabbix (daniel@firewall-services.com)
|
||||
|
||||
* Wed Jul 04 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.40-1
|
||||
- Fix ZFS pool stats retrieval (daniel@firewall-services.com)
|
||||
|
||||
* Wed Jun 13 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.39-1
|
||||
- Fix computing pool CPU usage in check_pve (daniel@firewall-services.com)
|
||||
|
||||
* Thu Jun 07 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.38-1
|
||||
- Add global net and disk stats for the cluster in check_pve_sudo
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Tue Jun 05 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.37-1
|
||||
- Fix check_pve_sudo for single node monitoring (daniel@firewall-services.com)
|
||||
|
||||
* Tue Jun 05 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.36-1
|
||||
- Remove redundant condition (daniel@firewall-services.com)
|
||||
- Fix {#PVE_STOR_STATUS} macro (daniel@firewall-services.com)
|
||||
- Only gather info about online nodes (daniel@firewall-services.com)
|
||||
- Add some global cluster stats for PVE (daniel@firewall-services.com)
|
||||
|
||||
* Sun Jun 03 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.35-1
|
||||
- Enhance PVE scripts and conf (daniel@firewall-services.com)
|
||||
- Add basic scripts for PVE monitoring (daniel@firewall-services.com)
|
||||
|
||||
* Wed May 30 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.34-1
|
||||
- Add stats for ZFS zpools (daniel@firewall-services.com)
|
||||
|
||||
* Tue May 29 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.33-1
|
||||
- Ensure we always return a value for scan action status errors in check_zfs
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Tue May 29 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.32-1
|
||||
- Handle situations where there's more than 1000 errors on a item in ZFS pools
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Tue May 29 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.31-1
|
||||
- Various enhancements in check_zfs (daniel@firewall-services.com)
|
||||
- Fix macro name for zfs zpool discovery (daniel@firewall-services.com)
|
||||
|
||||
* Mon May 28 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.30-1
|
||||
- Rename vfs.zfs.discovery to vfs.zfs.zpool.discovery So later we'll be able to
|
||||
add other discovery rules for say, datasets (daniel@firewall-services.com)
|
||||
|
||||
* Mon May 28 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.29-1
|
||||
- Add scripts to discover and check ZFS zpools (daniel@firewall-services.com)
|
||||
|
||||
* Tue Mar 06 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.28-1
|
||||
- Use "all" key to get all httpd stats in JSON format (daniel@firewall-
|
||||
services.com)
|
||||
|
||||
* Tue Mar 06 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.27-1
|
||||
- Respond with all stats as a JSON structure if no --what given
|
||||
(daniel@firewall-services.com)
|
||||
|
||||
* Tue Mar 06 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.26-1
|
||||
- Support space in httpd status key So total_accesses and total_kbytes are
|
||||
available again (daniel@firewall-services.com)
|
||||
|
||||
* Tue Feb 06 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.25-1
|
||||
- Fix mdadm RAID discovery condition (daniel@firewall-services.com)
|
||||
|
||||
* Tue Jan 09 2018 Daniel Berteaud <daniel@firewall-services.com> 0.2.24-1
|
||||
- Don't WARN when device is being checked, only when it's rebuilding
|
||||
(daniel@firewall-services.com)
|
||||
- Don't detect mdadm RAID in containers (daniel@firewall-services.com)
|
||||
|
||||
* Thu Nov 30 2017 Daniel Berteaud <daniel@firewall-services.com> 0.2.23-1
|
||||
- Check line format in check_httpd Instead of spliting errors in case server-
|
||||
status redirect to somewhere else (daniel@firewall-services.com)
|
||||
|
||||
* Mon Nov 20 2017 Daniel Berteaud <daniel@firewall-services.com> 0.2.22-1
|
||||
- Add script to monitor spamassassin's bayes database stats (daniel@firewall-
|
||||
services.com)
|
||||
- Symlink releasrs.conf to global's one (daniel@firewall-services.com)
|
||||
|
||||
* Tue Nov 14 2017 Daniel Berteaud <daniel@firewall-services.com> 0.2.21-1
|
||||
- Remove now non existing CHANGELOG.git file (daniel@firewall-services.com)
|
||||
|
||||
* Tue Nov 14 2017 Daniel Berteaud <daniel@firewall-services.com> 0.2.20-1
|
||||
- new package built with tito
|
||||
|
||||
* Thu Oct 12 2017 Daniel Berteaud <daniel@firewall-services.com> - 0.2.19-1
|
||||
- Correctly handle Partially Degraded state
|
||||
|
||||
* Thu Aug 24 2017 Daniel Berteaud <daniel@firewall-services.com> - 0.2.18-1
|
||||
- Only include SELinux policy module on el7
|
||||
|
||||
* Wed Aug 23 2017 Daniel Berteaud <daniel@firewall-services.com> - 0.2.17-1
|
||||
- Add a SELinux policy module
|
||||
|
||||
* Wed Jun 14 2017 Daniel Berteaud <daniel@firewall-services.com> - 0.2.16-1
|
||||
- Add kernel.openedfile UserParameter
|
||||
|
||||
* Thu Nov 24 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.15-1
|
||||
- Fix discovery scripts to always return a valid JSON value, even if empty
|
||||
(sensors, lvm and nut_ups)
|
||||
|
||||
* Wed Nov 9 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.14-1
|
||||
- Add scripts to monitor apache httpd
|
||||
|
||||
* Sun Oct 30 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.13-1
|
||||
- Fix handling Airflow_Temperature_Cel label
|
||||
|
||||
* Fri Oct 28 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.12-1
|
||||
- Support Airflow_Temperature_Cel as temp label for smartctl based sensors
|
||||
|
||||
* Thu Sep 1 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.11-1
|
||||
- Add support for lm_sensors based sensors
|
||||
|
||||
* Thu Aug 25 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.10-1
|
||||
- Add monitoring item for squid's FD
|
||||
|
||||
* Wed Apr 6 2016 Daniel Berteaud <daniel@firewall-services.com> - 0.2.9-1
|
||||
- Detect HDD temp sensors on sat+megaraid controllers
|
||||
|
||||
* Mon Mar 21 2016 Daniel B. <daniel@firewall-services.com> - 0.2.8-1
|
||||
- Prevent running several gluster check commands at the same time
|
||||
|
||||
* Wed Sep 16 2015 Daniel B. <daniel@firewall-services.com> - 0.2.7-1
|
||||
- Prevent GlusterFS heal false positive due to concurrent locking
|
||||
|
||||
* Mon Sep 14 2015 Daniel B. <daniel@firewall-services.com> - 0.2.6-1
|
||||
- Add script to discover and monitor DRBD resources
|
||||
|
||||
* Wed Sep 9 2015 Daniel B. <daniel@firewall-services.com> - 0.2.5-1
|
||||
- Support negative values for temp sensors
|
||||
|
||||
* Mon Jul 27 2015 Daniel B. <daniel@firewall-services.com> - 0.2.4-1
|
||||
- Several enhancements in sensors ini generator
|
||||
|
||||
* Fri Jul 24 2015 Daniel B. <daniel@firewall-services.com> - 0.2.3-1
|
||||
- Separate UPS default threshold
|
||||
- Minor coding style updates
|
||||
|
||||
* Mon Jul 20 2015 Daniel B. <daniel@firewall-services.com> - 0.2.2-1
|
||||
- Start working on perl libs to reduce code duplication
|
||||
- Detect nut UPS temp sensors
|
||||
|
||||
* Fri Jul 10 2015 Daniel B. <daniel@firewall-services.com> - 0.2.1-1
|
||||
- Fix GlusterFS brick count on 3.7.x
|
||||
|
||||
* Fri Jul 10 2015 Daniel B. <daniel@firewall-services.com> - 0.2.0-1
|
||||
- Migrate sensors config to an ini format
|
||||
- Add a generator script which detects available sensors
|
||||
|
||||
* Tue Jul 7 2015 Daniel B. <daniel@firewall-services.com> - 0.1.27-1
|
||||
- Support different sensors types
|
||||
|
||||
* Thu Jun 4 2015 Daniel B. <daniel@firewall-services.com> - 0.1.26-1
|
||||
- Alert if a self heal is in progress on a glusterfs vol
|
||||
|
||||
* Thu Jun 4 2015 Daniel B. <daniel@firewall-services.com> - 0.1.25-1
|
||||
- Fix gluster checks if info heal-failed is not supported
|
||||
|
||||
* Wed Apr 15 2015 Daniel B. <daniel@firewall-services.com> - 0.1.24-1
|
||||
- Report a warning if a RAID array is resyncing
|
||||
|
||||
* Tue Feb 10 2015 Daniel B. <daniel@firewall-services.com> - 0.1.23-1
|
||||
- Fix disco_filesystem to output valid JSON
|
||||
|
||||
* Thu Jan 8 2015 Daniel B. <daniel@firewall-services.com> - 0.1.22-1
|
||||
- Fix check_qmail_sudo
|
||||
|
||||
* Mon Jan 5 2015 Daniel B. <daniel@firewall-services.com> - 0.1.21-1
|
||||
- Add scripts to check qmail (requires qmqtool)
|
||||
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
# Discovery of configured host
|
||||
# Key: backuppc.host.discovery
|
||||
# Macro: {#BPCSTATUS}
|
||||
# Filter regex: enabled => true
|
||||
# Filter regex: enabled|1 => true
|
||||
# Other available macros:
|
||||
# {#BPCPERIOD}: Max age (in day) the oldest backup should be
|
||||
# {#BPCHOST}: name of the backup host
|
||||
UserParameter=backuppc.host.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_backuppc_sudo --base64 --regex=$1
|
||||
UserParameter=backuppc.host.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_backuppc_sudo --hosts
|
||||
UserParameter=backuppc.entity.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_backuppc_sudo --entities
|
||||
|
||||
# Item prototypes
|
||||
# key: backuppc.host.info[{#BPCHOST},item]
|
||||
# Valide item are: errors, max_errors, size, duration, age, notify
|
||||
UserParameter=backuppc.host.info[*],/usr/bin/sudo /var/lib/zabbix/bin/check_backuppc_sudo $1 $2
|
||||
# key: backuppc.host[{#BPCHOST}]
|
||||
# or
|
||||
# key: backuppc.entity[{#BPC_ENTITY}]
|
||||
# Returns a JSON object, use dependent item to split it
|
||||
UserParameter=backuppc.host[*],/usr/bin/sudo /var/lib/zabbix/bin/check_backuppc_sudo --host=$1
|
||||
UserParameter=backuppc.entity[*],/usr/bin/sudo /var/lib/zabbix/bin/check_backuppc_sudo --entity=$1
|
||||
|
||||
# key: backuppc.host[{#BPCHOST}]
|
||||
# or
|
||||
# key: backuppc.general
|
||||
# Same as entity checks for will process every hosts
|
||||
# Returns a JSON object, use dependent item to split it
|
||||
UserParameter=backuppc.general,/usr/bin/sudo /var/lib/zabbix/bin/check_backuppc_sudo --general
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
# Discover block devices
|
||||
UserParameter=vfs.dev.discovery,/var/lib/zabbix/bin/disco_block_devices
|
||||
# For Zabbix AGent < 4.4 you can uncomment this
|
||||
#UserParameter=vfs.dev.discovery,/var/lib/zabbix/bin/disco_block_devices
|
||||
|
|
9
zabbix_conf/docker.conf
Normal file
9
zabbix_conf/docker.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Discover Docker items
|
||||
# $1 can be containers, networks, volumes
|
||||
UserParameter=container.docker.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_docker_sudo --what $1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# container.docker.check.all[type,id]
|
||||
# Where type is what to monitor (global, container, network, volume)
|
||||
# id is the id of the item to monitor. Can be a name or an ID. For the global check, there's no ID
|
||||
UserParameter=container.docker.check[*],/usr/bin/sudo /var/lib/zabbix/bin/check_docker_sudo --$1 $2
|
6
zabbix_conf/drbd.conf
Normal file
6
zabbix_conf/drbd.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Discover DRBD resources
|
||||
UserParameter=drbd.resource.discovery[*],/var/lib/zabbix/bin/disco_drbd
|
||||
|
||||
# DRBD status
|
||||
UserParameter=drbd.resource.status[*],/var/lib/zabbix/bin/check_drbd --resource=$1 --what=$2
|
||||
|
2
zabbix_conf/elasticsearch.conf
Normal file
2
zabbix_conf/elasticsearch.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
UserParameter=elasticsearch.discovery[*],/var/lib/zabbix/bin/disco_elasticsearch --url=$1 --user=$2 --pass=$3 --$4
|
||||
UserParameter=elasticsearch.check[*],/var/lib/zabbix/bin/check_elasticsearch --url=$1 --user=$2 --pass=$3 --$4 $5
|
1
zabbix_conf/file_descr.conf
Normal file
1
zabbix_conf/file_descr.conf
Normal file
|
@ -0,0 +1 @@
|
|||
UserParameter=kernel.openedfiles,cat /proc/sys/fs/file-nr | awk '{print $1}'
|
6
zabbix_conf/httpd.conf
Normal file
6
zabbix_conf/httpd.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Discover if an httpd instance is running and has mod_status available on http://127.0.0.1/server-status
|
||||
# Just return {#HTTPD_STATUS_AVAILABLE} => 'yes' if found
|
||||
UserParameter=httpd.discovery,/var/lib/zabbix/bin/disco_httpd
|
||||
|
||||
# Stats to get
|
||||
UserParameter=httpd[*],/var/lib/zabbix/bin/check_httpd --uri $1 --what $2
|
6
zabbix_conf/icmp.conf
Normal file
6
zabbix_conf/icmp.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
# net.icmp takes two args. The host to ping (either an IP or a host name), and one of
|
||||
# * all: returns info in JSON format
|
||||
# * latency: returns latency in seconds. Floating number
|
||||
# * respond: returns 0 if no response where received, 1 otherwise
|
||||
# * loss: returns % of packet loss. Floating number
|
||||
UserParameter=net.icmp[*],/usr/bin/sudo /var/lib/zabbix/bin/check_icmp_sudo $1 --info=$2
|
|
@ -5,4 +5,5 @@ UserParameter=vfs.lvm.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_lvm_s
|
|||
# Type: Agent or Agent (active)
|
||||
# Key: vfs.lvm.lv[volume,key] where volume is the path to a logical volume and
|
||||
# key can be size, allocation (for snapshots only) or status
|
||||
UserParameter=vfs.lvm.lv[*],/usr/bin/sudo /var/lib/zabbix/bin/check_lvm_sudo $1 $2
|
||||
UserParameter=vfs.lvm.lv[*],/usr/bin/sudo /var/lib/zabbix/bin/check_lvm_sudo --lv='$1' --what='$2'
|
||||
UserParameter=vfs.lvm.vg[*],/usr/bin/sudo /var/lib/zabbix/bin/check_lvm_sudo --vg='$1' --what='$2'
|
||||
|
|
6
zabbix_conf/mpath.conf
Normal file
6
zabbix_conf/mpath.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Discover multipath devices
|
||||
# $1 not used for now
|
||||
UserParameter=vfs.mpath.discovery[*],sudo /var/lib/zabbix/bin/disco_mpath_sudo --$1
|
||||
|
||||
# Check multipath device
|
||||
UserParameter=vfs.mpath.info[*],sudo /var/lib/zabbix/bin/check_mpath_sudo --mpath=$1
|
7
zabbix_conf/mysql.conf
Normal file
7
zabbix_conf/mysql.conf
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Type: Agent or Agent (active)
|
||||
# You can also get all the stats in a json object by passing 'all',
|
||||
# or retreive the value of a specific key
|
||||
# Run the script without --what to get a list of available keys
|
||||
|
||||
UserParameter=db.mysql[*],sudo /var/lib/zabbix/bin/check_mysql_sudo --host '$1' --port '$2' --user '$3' --password '$4' --defaults '$5' --what '$6'
|
||||
|
5
zabbix_conf/nginx.conf
Normal file
5
zabbix_conf/nginx.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Discover if an nginx instance is running and has status handler running on http://localhost/nginx-status
|
||||
UserParameter=nginx.discovery,/var/lib/zabbix/bin/disco_nginx
|
||||
|
||||
# Stats to get
|
||||
UserParameter=nginx.status[*],/var/lib/zabbix/bin/check_nginx --uri $1 --what $2
|
|
@ -7,7 +7,7 @@
|
|||
# Units: %
|
||||
# Multiplier: Do not use
|
||||
# Store Value: As is
|
||||
UserParameter=ups.load[*],upsc $1 ups.load
|
||||
UserParameter=ups.load[*],upsc $1 ups.load 2>/dev/null
|
||||
|
||||
# Description: Nut UPS Battery Charge
|
||||
# Type: Agent or Agent (active)
|
||||
|
@ -16,23 +16,23 @@ UserParameter=ups.load[*],upsc $1 ups.load
|
|||
# Units: %
|
||||
# Multiplier: Do not use
|
||||
# Store Value: As is
|
||||
UserParameter=ups.battery.charge[*],upsc $1 battery.charge
|
||||
UserParameter=ups.battery.charge[*],upsc $1 battery.charge 2>/dev/null
|
||||
|
||||
# Description: Nut UPS Status
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: ups.status[UPS]
|
||||
# Type of information: Character
|
||||
# Show Value: As is (you can also define a dictionnary OL=>On Line etc...)
|
||||
UserParameter=ups.status[*],upsc $1 ups.status
|
||||
UserParameter=ups.status[*],upsc $1 ups.status 2>/dev/null
|
||||
|
||||
# Description: Nut UPS Model
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: ups.model[UPS]
|
||||
# Type of information: Text
|
||||
UserParameter=ups.model[*],upsc $1 ups.model
|
||||
UserParameter=ups.model[*],upsc $1 ups.model 2>/dev/null
|
||||
|
||||
# UPS discovery
|
||||
UserParameter=hardware.ups.discovery[*],/var/lib/zabbix/bin/disco_nut_ups $1
|
||||
|
||||
# This is a new, more generic nut ups UserParameter
|
||||
UserParameter=hardware.ups[*],upsc $1 $2
|
||||
UserParameter=hardware.ups[*],upsc $1 $2 2>/dev/null
|
||||
|
|
9
zabbix_conf/pmg.conf
Normal file
9
zabbix_conf/pmg.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Discover PMG items
|
||||
# $1 can be domains
|
||||
UserParameter=pmg.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_pmg_sudo --what $1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# pmg.check.all[type,id]
|
||||
# Where type is what to monitor (domain)
|
||||
# id is the id of the item to monitor. Eg, the domain name
|
||||
UserParameter=pmg.check.all[*],/usr/bin/sudo /var/lib/zabbix/bin/check_pmg_sudo --timespan=$1 --spamthres=$2 --$3 $4
|
10
zabbix_conf/pve.conf
Normal file
10
zabbix_conf/pve.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Discover PVE items
|
||||
# $1 can be nodes, guests, storage or pools
|
||||
UserParameter=pve.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_pve_sudo --what $1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# pve.check.all[type,id]
|
||||
# Where type is what to monitor (pool, storage, node, cluster, guest)
|
||||
# id is the id of the item to monitor. For a guest, it's his numerical ID, for a storage
|
||||
# a node or a pool, its name. For the cluster, there's no ID
|
||||
UserParameter=pve.check.all[*],/usr/bin/sudo /var/lib/zabbix/bin/check_pve_sudo --cache=300 --$1 $2
|
13
zabbix_conf/sa_learn.conf
Normal file
13
zabbix_conf/sa_learn.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Description: SA Learn statistics
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: mail.bayes
|
||||
# Type of information: Text
|
||||
# Units: N/A
|
||||
# Custom multiplier: Do not use
|
||||
# Store Value: As is
|
||||
# This is a master item which must then be splited with preprocessing (Zabbix >= 3.4.0)
|
||||
|
||||
UserParameter=mail.bayes.all,/usr/bin/sudo /var/lib/zabbix/bin/check_sa_learn_sudo
|
||||
|
||||
# Or you can use individual items. Valid arg are ham, spam and token
|
||||
UserParameter=mail.bayes[*],/usr/bin/sudo /var/lib/zabbix/bin/check_sa_learn_sudo --what=$1
|
7
zabbix_conf/samba_dc.conf
Normal file
7
zabbix_conf/samba_dc.conf
Normal file
|
@ -0,0 +1,7 @@
|
|||
UserParameter=samba_dc.discovery[*],sudo /var/lib/zabbix/bin/disco_samba_dc_sudo --what='$1'
|
||||
# Create a text item with key samba_dc.info[300] and a check interval of 300
|
||||
# Then use dependent item to get individual counters
|
||||
UserParameter=samba_dc.info[*],sudo /var/lib/zabbix/bin/check_samba_dc_sudo --since='$1'
|
||||
# Create a text item with key samba_dc.ou[{#SAMBA_OU}], then use dependant items with JSONPath to get individual info
|
||||
UserParameter=samba_dc.ou[*],sudo /var/lib/zabbix/bin/check_samba_dc_sudo --ou='$1'
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Sensors discovery
|
||||
# See /etc/zabbix/sensors.conf
|
||||
UserParameter=hardware.sensor.discovery,/var/lib/zabbix/bin/disco_sensors
|
||||
UserParameter=hardware.sensor.discovery[*],/var/lib/zabbix/bin/disco_sensors --type=$1
|
||||
|
||||
# Sensors
|
||||
UserParameter=hardware.sensor[*],/usr/bin/sudo /var/lib/zabbix/bin/check_sensors_sudo $1 $2
|
||||
|
|
|
@ -5,3 +5,7 @@ UserParameter=hardware.disk.smart.discovery,/usr/bin/sudo /var/lib/zabbix/bin/di
|
|||
# Takes two args: the drives to check, and the value to get
|
||||
# eg: hardward.disk.smart[/dev/sda,Reallocated_Sector_Ct]
|
||||
UserParameter=hardware.disk.smart[*],/usr/bin/sudo /var/lib/zabbix/bin/check_smart_sudo $1 $2
|
||||
|
||||
# New smart disk discovery/monitoring
|
||||
UserParameter=stor.dev.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_stor_dev_sudo
|
||||
UserParameter=stor.dev.info[*],/usr/bin/sudo /var/lib/zabbix/bin/check_stor_dev_sudo --dev "$1" --type "$2"
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
# Squid
|
||||
|
||||
|
||||
# Discover if a squid instance is running and has status handler running on http://127.0.0.1:3128/squid-internal-mgr/info
|
||||
UserParameter=squid.discovery[*],/var/lib/zabbix/bin/disco_squid
|
||||
|
||||
# Stats to get
|
||||
UserParameter=squid.check[*],/var/lib/zabbix/bin/check_squid --what $1
|
||||
|
||||
################################################
|
||||
## LEGACY SQUID ITEMS
|
||||
################################################
|
||||
|
||||
# Description: Squid Request Hit Ratio
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: squid.request_hit_ratio
|
||||
|
@ -50,3 +61,33 @@ UserParameter=squid.cache_size_disk,squidclient mgr:info|grep 'Storage Swap size
|
|||
|
||||
UserParameter=squid.cache_size_mem,squidclient mgr:info|grep 'Storage Mem size:' | awk '{print $4}'
|
||||
|
||||
# Description: Squid FD limit
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: squid.fd_max
|
||||
# Type of information: Numeric (integer 64bits)
|
||||
# Units: N/A
|
||||
# Custom multiplier: Do not use
|
||||
# Store Value: As is
|
||||
|
||||
UserParameter=squid.max_fd,squidclient mgr:info | grep 'Maximum number of file descriptors' | cut -d':' -f2 | tr -d ' \t'
|
||||
|
||||
# Description: Squid reserved FD
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: squid.fd_reserved
|
||||
# Type of information: Numeric (integer 64bits)
|
||||
# Units: N/A
|
||||
# Custom multiplier: Do not use
|
||||
# Store Value: As is
|
||||
|
||||
UserParameter=squid.reserved_fd,squidclient mgr:info | grep 'Reserved number of file descriptors' | cut -d':' -f2 | tr -d ' \t'
|
||||
|
||||
# Description: Squid available FD
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: squid.fd_available
|
||||
# Type of information: Numeric (integer 64bits)
|
||||
# Units: N/A
|
||||
# Custom multiplier: Do not use
|
||||
# Store Value: As is
|
||||
|
||||
UserParameter=squid.available_fd,squidclient mgr:info | grep 'Available number of file descriptors' | cut -d':' -f2 | tr -d ' \t'
|
||||
|
||||
|
|
2
zabbix_conf/unifi.conf
Normal file
2
zabbix_conf/unifi.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
UserParameter=unifi.discovery[*],/var/lib/zabbix/bin/disco_unifi --url=$1 --user=$2 --pass=$3 --site=$4 --what=$5 --type=$6
|
||||
UserParameter=unifi.check.all[*],/var/lib/zabbix/bin/check_unifi --url=$1 --user=$2 --pass=$3 --site=$4 --$5 $6
|
12
zabbix_conf/vdo.conf
Normal file
12
zabbix_conf/vdo.conf
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Discover VDO volumes
|
||||
# $1 not used for now
|
||||
UserParameter=vfs.vdo.discovery[*],/var/lib/zabbix/bin/disco_vdo_sudo --what=$1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# Key: vfs.vdo.vol[volume,item] where volume is the name of the volume to monitor
|
||||
# item can be one of the valid keys (run manually without --value arg to see available keys)
|
||||
UserParameter=vfs.vdo.vol[*],sudo /var/lib/zabbix/bin/check_vdo_sudo --volume=$1 --value=$2
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# You can also get all the info about a vdo volume at once, in JSON
|
||||
UserParameter=vfs.vdo.vol.all[*],sudo /var/lib/zabbix/bin/check_vdo_sudo --volume=$1
|
19
zabbix_conf/zfs.conf
Normal file
19
zabbix_conf/zfs.conf
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Discover ZFS zpools
|
||||
# $1 not used for now
|
||||
UserParameter=vfs.zfs.discovery[*],/var/lib/zabbix/bin/disco_zfs --$1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# You can also get all the info about a zpool at once, in JSON
|
||||
UserParameter=vfs.zfs.zpool.info[*],/var/lib/zabbix/bin/check_zfs --zpool=$1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# FS, Zvol or Snap info in JSON
|
||||
UserParameter=vfs.zfs.dataset.info[*],/var/lib/zabbix/bin/check_zfs --dataset=$1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# Sanoïd snapshot monitoring
|
||||
UserParameter=vfs.zfs.sanoid.check[*],/var/lib/zabbix/bin/check_zfs --sanoid=$1
|
||||
|
||||
# Type: Agent or Agent (active)
|
||||
# ARC stats
|
||||
UserParameter=vfs.zfs.stats.all[*],/var/lib/zabbix/bin/check_zfs --stats=$1
|
11
zabbix_conf/zimbra.conf
Normal file
11
zabbix_conf/zimbra.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Discovery of configured host
|
||||
# Key: zimbra.discovery[services] or zimbra.discovery[servers]
|
||||
# Macro: {#ZM_SERVICE}
|
||||
# Other available macros:
|
||||
UserParameter=zimbra.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_zimbra_sudo --$1
|
||||
|
||||
# Item prototypes
|
||||
# key: zimbra.check[*]
|
||||
# or
|
||||
# Returns a JSON object, use dependent item to split it
|
||||
UserParameter=zimbra.status[*],/usr/bin/sudo /var/lib/zabbix/bin/check_zimbra_sudo --status=$1
|
|
@ -1,10 +1,27 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use lib "/usr/share/BackupPC/lib";
|
||||
use lib "/usr/share/backuppc/lib";
|
||||
use lib "/usr/local/BackupPC/lib";
|
||||
use BackupPC::Lib;
|
||||
use BackupPC::CGI::Lib;
|
||||
use POSIX;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use Statistics::Descriptive;
|
||||
use Data::Dumper;
|
||||
|
||||
my $general = 0;
|
||||
my $host = undef;
|
||||
my $entity = undef;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"general" => \$general,
|
||||
"host=s" => \$host,
|
||||
"entity=s" => \$entity,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
# We need to switch to backuppc UID/GID
|
||||
my $uid = getuid();
|
||||
|
@ -13,73 +30,157 @@ my (undef,undef,$bkpuid,$bkpgid) = getpwnam('backuppc');
|
|||
setuid($bkpuid) if ($uid ne $bkpuid);
|
||||
setgid($bkpgid) if ($gid ne $bkpgid);
|
||||
|
||||
my $host = $ARGV[0];
|
||||
my $what = $ARGV[1];
|
||||
|
||||
my $bpc = BackupPC::Lib->new();
|
||||
my @backups = $bpc->BackupInfoRead($host);
|
||||
my $mainConf = $bpc->ConfigDataRead();
|
||||
my $hostConf = $bpc->ConfigDataRead($host);
|
||||
my $conf = { %$mainConf, %$hostConf };
|
||||
my $fullCnt = $incrCnt = 0;
|
||||
my $fullAge = $incrAge = $lastAge = -1;
|
||||
my $lastXferErrors = 0;
|
||||
my $maxErrors = 0;
|
||||
my $json = {};
|
||||
|
||||
for ( my $i = 0 ; $i < @backups ; $i++ ) {
|
||||
if ( $backups[$i]{type} eq "full" ) {
|
||||
$fullCnt++;
|
||||
if ( $fullAge < 0 || $backups[$i]{startTime} > $fullAge ) {
|
||||
$fullAge = $backups[$i]{startTime};
|
||||
$fullSize = $backups[$i]{size};
|
||||
$fullDur = $backups[$i]{endTime} - $backups[$i]{startTime};
|
||||
}
|
||||
}
|
||||
else {
|
||||
$incrCnt++;
|
||||
if ( $incrAge < 0 || $backups[$i]{startTime} > $incrAge ) {
|
||||
$incrAge = $backups[$i]{startTime};
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $fullAge > $incrAge && $fullAge >= 0 ) {
|
||||
$lastAge = $fullAge;
|
||||
}
|
||||
else {
|
||||
$lastAge = $incrAge;
|
||||
}
|
||||
if ( $lastAge < 0 ) {
|
||||
$lastAge = "";
|
||||
}
|
||||
else {
|
||||
$lastAge = sprintf("%.1f", (time - $lastAge) / (24 * 3600));
|
||||
}
|
||||
$lastXferErrors = $backups[@backups-1]{xferErrs} if ( @backups );
|
||||
$maxErrors = $conf->{MaxXferError} if (defined $conf->{MaxXferError});
|
||||
if ( $host ) {
|
||||
my $hostConf = $bpc->ConfigDataRead($host);
|
||||
my $conf = { %$mainConf, %$hostConf };
|
||||
$json = {
|
||||
bkp => 0,
|
||||
full_size => 0,
|
||||
total_size => 0,
|
||||
history_size => 0,
|
||||
errors => 0,
|
||||
new_size => 0,
|
||||
new_size_avg => 0,
|
||||
new_size_median => 0,
|
||||
new_size_q1 => 0,
|
||||
new_size_q3 => 0,
|
||||
duration => 0,
|
||||
comp_ratio => 0,
|
||||
enabled => 0,
|
||||
max_errors => 0,
|
||||
age => 0,
|
||||
type => 'none'
|
||||
};
|
||||
|
||||
if ($what eq 'errors'){
|
||||
print $lastXferErrors;
|
||||
}
|
||||
elsif ($what eq 'max_errors'){
|
||||
print $maxErrors;
|
||||
}
|
||||
elsif ($what eq 'age'){
|
||||
print $lastAge;
|
||||
}
|
||||
elsif ($what eq 'size'){
|
||||
print $fullSize;
|
||||
}
|
||||
elsif ($what eq 'duration'){
|
||||
print $fullDur;
|
||||
}
|
||||
elsif ($what eq 'notify'){
|
||||
print $conf->{EMailNotifyOldBackupDays};
|
||||
}
|
||||
else{
|
||||
my $new_size_of_last_full = 0;
|
||||
my @bpc_info = $bpc->BackupInfoRead($host);
|
||||
my $sizes = new Statistics::Descriptive::Full;
|
||||
|
||||
if ( scalar( @bpc_info ) ){
|
||||
foreach my $backup ( @bpc_info ) {
|
||||
# Skip partial or active backups
|
||||
next if ( $backup->{type} !~ m/^full|incr$/ );
|
||||
if ( $backup->{type} eq "full" ) {
|
||||
$json->{full_size} = $backup->{size};
|
||||
$new_size_of_last_full = $backup->{sizeNew} if $backup->{num} > 0;
|
||||
}
|
||||
# Push all the sizes in our data set to compute avg sizes
|
||||
# Exclude backup N°0 as it'll always have much more new data than normal backups
|
||||
# Also exclude if size is not defined. This can happen in BackupPC v3 when
|
||||
# the BackupPC_link process is waiting for the nightly to finish
|
||||
$sizes->add_data($backup->{sizeNew}) if ( $backup->{num} > 0 && $backup->{sizeNew} );
|
||||
$json->{bkp}++;
|
||||
}
|
||||
|
||||
# Ignore the last backup if it's not full or incr (which means it's either partial or active)
|
||||
my $i = ( $bpc_info[-1]->{type} =~ m/^full|incr$/ ) ? -1 : -2;
|
||||
|
||||
$json->{errors} = $bpc_info[$i]->{xferErrs};
|
||||
$json->{duration} = $bpc_info[$i]->{endTime} - $bpc_info[$i]->{startTime};
|
||||
$json->{type} = $bpc_info[$i]->{type};
|
||||
|
||||
$json->{new_size_avg} = int $sizes->mean;
|
||||
$json->{new_size_median} = int $sizes->median;
|
||||
|
||||
# Some old versions of Statistics::Descriptive (eg, on el5) do not support quantile
|
||||
$json->{new_size_q1} = eval { int $sizes->quantile(1) } || 0;
|
||||
$json->{new_size_q3} = eval { int $sizes->quantile(3) } || 0;
|
||||
$json->{enabled} = ( $conf->{BackupsDisable} > 0 ) ? 0 : 1;
|
||||
$json->{total_size} = $sizes->sum + $json->{full_size} - $new_size_of_last_full;
|
||||
$json->{history_size} = $json->{total_size} - $json->{full_size};
|
||||
$json->{age} = time - $bpc_info[$i]->{startTime};
|
||||
|
||||
# For sizeNew, we need to wait for BackupPC_link to run, which can be delayed
|
||||
# if a nightly process is running. In this case, use the stats from the previous backup
|
||||
# Except when we ave a single backup, in which case we read stats of this only backup
|
||||
$i = ( $bpc_info[-1]->{sizeNew} || scalar @bpc_info == 1 ) ? -1 : -2;
|
||||
$json->{new_size} = $bpc_info[$i]->{sizeNew};
|
||||
$json->{comp_ratio} = ( $bpc_info[$i]->{sizeNew} > 0 ) ?
|
||||
sprintf( "%.2f", 100 - ( $bpc_info[$i]->{sizeNewComp} * 100 / $bpc_info[$i]->{sizeNew} ) )
|
||||
:
|
||||
0;
|
||||
|
||||
$json->{max_errors} = $conf->{MaxXferError} || 0;
|
||||
}
|
||||
} elsif ( $entity or $general) {
|
||||
|
||||
$json = {
|
||||
perf => 0,
|
||||
size => 0,
|
||||
full_size => 0,
|
||||
total_size => 0,
|
||||
history_size => 0,
|
||||
hosts => 0,
|
||||
bkp => 0,
|
||||
ratio => 0
|
||||
};
|
||||
|
||||
my $entity_total_new = 0;
|
||||
my $entity_total_comp = 0;
|
||||
|
||||
foreach my $host ( keys %{ $bpc->HostInfoRead } ) {
|
||||
next unless ($host =~ m/^(vm_)?\Q$entity\E_.*/ or $general);
|
||||
my $full_size;
|
||||
|
||||
$json->{hosts}++;
|
||||
|
||||
my $hostConf = $bpc->ConfigDataRead($host);
|
||||
my $conf = { %$mainConf, %$hostConf };
|
||||
my $freq = ( $conf->{FullPeriod} > $conf->{IncrPeriod} ) ? $conf->{IncrPeriod} : $conf->{FullPeriod};
|
||||
my $host_duration = 0;
|
||||
my $host_bkp_num = 0;
|
||||
my $host_new_size = 0;
|
||||
my $host_full_size = 0;
|
||||
my $host_new_size_of_last_full = 0;
|
||||
|
||||
foreach my $backup ( $bpc->BackupInfoRead( $host ) ) {
|
||||
next if ( $backup->{type} !~ m/^full|incr$/ );
|
||||
|
||||
# Save the total size of the last full backup
|
||||
if ( $backup->{type} eq 'full' ) {
|
||||
$host_full_size = $backup->{size};
|
||||
$host_new_size_of_last_full = $backup->{sizeNew} if $backup->{num} > 0;
|
||||
}
|
||||
$host_new_size += $backup->{sizeNew} if ( $backup->{num} > 0 && $backup->{sizeNew} );
|
||||
|
||||
$entity_total_new += $backup->{sizeNew};
|
||||
$entity_total_comp += $backup->{sizeNewComp};
|
||||
$host_duration += $backup->{endTime} - $backup->{startTime};
|
||||
$host_bkp_num++;
|
||||
$json->{bkp}++;
|
||||
}
|
||||
# Compute the average cost as the number of hours per day spent
|
||||
# to backup this host
|
||||
$json->{perf} += ( $host_bkp_num > 0 ) ? $host_duration / ( 3600 * $host_bkp_num * $freq ) : 0;
|
||||
|
||||
# $json->{size} represents the total size used by this host.
|
||||
# But we want to substract the new size of the last full, as for this one we
|
||||
# do not count sizeNew but size
|
||||
my $host_total_size = $host_new_size + $host_full_size - $host_new_size_of_last_full;
|
||||
|
||||
# This one is kept just for compatibility. New Zabbix template will use total_size
|
||||
$json->{size} += $host_total_size;
|
||||
$json->{total_size} += $host_total_size;
|
||||
$json->{full_size} += $host_full_size;
|
||||
$json->{history_size} += $host_total_size - $host_full_size;
|
||||
}
|
||||
$json->{ratio} = ( $entity_total_new > 0 ) ? 100 - ( $entity_total_comp * 100 / $entity_total_new ) : 0;
|
||||
|
||||
# Round some values
|
||||
foreach my $key ( qw(ratio perf) ) {
|
||||
$json->{$key} = sprintf( "%.2f", $json->{$key} );
|
||||
}
|
||||
} else {
|
||||
print<<"EOF";
|
||||
|
||||
Usage: $0 <host> [errors|age|size|duration]
|
||||
Usage: $0 --host=<host> or --entity=<entity>
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
print to_json( $json, { pretty => $pretty } );
|
||||
exit(0);
|
||||
|
|
90
zabbix_scripts/check_docker_sudo
Executable file
90
zabbix_scripts/check_docker_sudo
Executable file
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
use Date::Parse;
|
||||
|
||||
my $docker = which('docker');
|
||||
my $json = {};
|
||||
my $pretty = 0;
|
||||
my ($global, $container, $network, $volume) = undef;
|
||||
|
||||
GetOptions(
|
||||
'global' => \$global,
|
||||
'container=s' => \$container,
|
||||
'network=s' => \$network,
|
||||
'volume=s' => \$volume,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
# Sanitize args
|
||||
if (defined $container and not $container =~ m/^[a-zA-Z0-9\-_]+/){
|
||||
die "Invalid container ID $container\n";
|
||||
} elsif (defined $network and not $network =~ m/^[a-zA-Z0-9\-_]+/){
|
||||
die "Invalid network ID\n";
|
||||
} elsif (defined $volume and not $volume =~ m/^[a-zA-Z0-9\-_]+/){
|
||||
die "Invalid volume name\n";
|
||||
}
|
||||
|
||||
# Default formating
|
||||
my $format = '{{ json . }}';
|
||||
my $cmd;
|
||||
if ($global){
|
||||
$json->{info} = from_json(qx($docker info --format '$format'));
|
||||
} elsif (defined $container) {
|
||||
$json->{inspect} = from_json(qx($docker container inspect $container --format '$format'));
|
||||
$json->{stats} = from_json(qx($docker container stats $container --format '$format' --no-stream));
|
||||
# Remove percent sign so Zabbix can get raw value
|
||||
foreach my $stat (qw(MemPerc CPUPerc)){
|
||||
$json->{stats}->{$stat} =~ s/%$//;
|
||||
}
|
||||
# Extract mem usage vs mem limit, net in vs net out and blk read vs blk write
|
||||
($json->{stats}->{MemCurrent}, $json->{stats}->{MemLimit}) = split(/\s*\/\s*/, $json->{stats}->{MemUsage});
|
||||
($json->{stats}->{NetIOIn}, $json->{stats}->{NetIOOut}) = split(/\s*\/\s*/, $json->{stats}->{NetIO});
|
||||
($json->{stats}->{BlockIORead}, $json->{stats}->{BlockIOWrite}) = split(/\s*\/\s*/, $json->{stats}->{BlockIO});
|
||||
# Convert into Bytes
|
||||
foreach my $stat (qw(MemCurrent MemLimit NetIOIn NetIOOut BlockIORead BlockIOWrite)){
|
||||
$json->{stats}->{$stat} = convert_unit($json->{stats}->{$stat});
|
||||
}
|
||||
# Compute a useful Uptime from the StartedAt value
|
||||
if ($json->{inspect}->{State}->{Running}){
|
||||
$json->{stats}->{Uptime} = int(time() - str2time($json->{inspect}->{State}->{StartedAt}));
|
||||
} else {
|
||||
$json->{stats}->{Uptime} = 0;
|
||||
}
|
||||
} elsif (defined $network){
|
||||
$json->{inspect} = from_json(qx($docker network inspect $network --format '$format'));
|
||||
} elsif (defined $volume){
|
||||
$json->{inspect} = from_json(qx($docker volume inspect $volume --format '$format'));
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
||||
|
||||
|
||||
sub convert_unit {
|
||||
my $val = shift;
|
||||
my $suffix_multiplier = {
|
||||
ki => 1024,
|
||||
Ki => 1024,
|
||||
Mi => 1024 * 1024,
|
||||
Gi => 1024 * 1024 * 1024,
|
||||
Ti => 1024 * 1024 * 1024 * 1024,
|
||||
Pi => 1024 * 1024 * 1024 * 1024 * 1024,
|
||||
k => 1000,
|
||||
K => 1000,
|
||||
M => 1000 * 1000,
|
||||
G => 1000 * 1000 * 1000,
|
||||
T => 1000 * 1000 * 1000 * 1000,
|
||||
P => 1000 * 1000 * 1000 * 1000 * 1000
|
||||
};
|
||||
if ($val =~ m/^(\d+(\.\d+)?)(ki|Ki|Mi|Gi|Ti|Pi|k|K|M|G|T|P)?B/){
|
||||
$val = int($1 * $suffix_multiplier->{$3}) if (defined $3 and defined $suffix_multiplier->{$3});
|
||||
# Remove the Bytes suffix if remaining
|
||||
$val =~ s/B$//;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
46
zabbix_scripts/check_drbd
Normal file
46
zabbix_scripts/check_drbd
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
|
||||
my $what = 'cstate';
|
||||
my $resource = undef;
|
||||
my @supported = qw(cstate dstate role);
|
||||
|
||||
GetOptions(
|
||||
"what=s" => \$what,
|
||||
"resource=s" => \$resource
|
||||
);
|
||||
|
||||
my $drbdadm = which('drbdadm');
|
||||
|
||||
unless($drbdadm){
|
||||
die 'ZBX_NOTSUPPORTED';
|
||||
}
|
||||
|
||||
sub usage(){
|
||||
my $supp = join('|', @supported);
|
||||
print <<"EOF";
|
||||
|
||||
usage: $0 --what=[$supp] --resource=<drbd resource name>
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
unless ((grep { $_ eq $what } @supported) && $resource){
|
||||
usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
open RES, '-|', $drbdadm, $what, $resource || die "Can't open pipe: $!";
|
||||
my $out = join "", <RES>;
|
||||
close RES || die "An error occured: $!\n";
|
||||
chomp($out);
|
||||
# We only want the state of the local node
|
||||
if ($out =~ m{(.*)/.*}){
|
||||
$out = $1;
|
||||
}
|
||||
|
||||
print $out;
|
||||
exit 0;
|
94
zabbix_scripts/check_elasticsearch
Normal file
94
zabbix_scripts/check_elasticsearch
Normal file
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Request::Common;
|
||||
use URI;
|
||||
use Data::Dumper;
|
||||
|
||||
my $user = undef;
|
||||
my $pass = undef;
|
||||
my $url = 'http://localhost:9200';
|
||||
my $certcheck = 1;
|
||||
my $cluster = 0;
|
||||
my $node = undef;
|
||||
my $index = undef;
|
||||
my $pretty = 0;
|
||||
|
||||
my $json = {};
|
||||
|
||||
GetOptions (
|
||||
'user:s' => \$user,
|
||||
'password:s' => \$pass,
|
||||
'url=s' => \$url,
|
||||
'cert-check!' => \$certcheck,
|
||||
'cluster' => \$cluster,
|
||||
'node=s' => \$node,
|
||||
'index=s' => \$index,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
# If no option is given, default to fetch the cluster status
|
||||
if (not defined $cluster and not defined $node and not defined $index){
|
||||
$cluster = 1;
|
||||
}
|
||||
|
||||
my $uri = URI->new($url);
|
||||
|
||||
if (not defined $uri){
|
||||
die "COuldn't parse $url as a valid url\n";
|
||||
}
|
||||
|
||||
# If connecting over http or is host is localhost
|
||||
# there's no need to check certificate
|
||||
if ($uri->scheme eq 'http' or $uri->host =~ m/^localhost|127\.0\.0/){
|
||||
$certcheck = 0;
|
||||
}
|
||||
|
||||
my $resp;
|
||||
my $sslopts = {};
|
||||
if (not $certcheck){
|
||||
$sslopts = {
|
||||
verify_hostname => 0,
|
||||
SSL_verify_mode => 0
|
||||
}
|
||||
}
|
||||
|
||||
my $ua = LWP::UserAgent->new(
|
||||
ssl_opts => $sslopts
|
||||
);
|
||||
$ua->env_proxy;
|
||||
|
||||
if ($cluster){
|
||||
$json = make_request('/_cluster/stats');
|
||||
} elsif (defined $node){
|
||||
my $resp = make_request('/_nodes/' . $node)->{'nodes'};
|
||||
# We can specify node by ID, name or IP
|
||||
if (defined $resp->{$node}){
|
||||
$json = $resp->{$node};
|
||||
} else {
|
||||
my $node_id = (keys %{$resp})[0];
|
||||
$json = $resp->{$node_id};
|
||||
}
|
||||
} elsif (defined $index){
|
||||
$json = make_request('/_cluster/health/' . $index . '?level=indices')->{'indices'}->{$index};
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
||||
|
||||
sub make_request {
|
||||
my $path = shift;
|
||||
my $req_url = $url . $path;
|
||||
my $req = GET $req_url;
|
||||
if (defined $user and $user ne '' and defined $pass and $pass ne ''){
|
||||
$req->authorization_basic($user, $pass);
|
||||
}
|
||||
my $resp = $ua->request($req);
|
||||
die "Request to $req_url failed : " . $resp->message . "\n" if $resp->is_error;
|
||||
return from_json($resp->decoded_content);
|
||||
}
|
||||
|
|
@ -10,12 +10,16 @@ my $peer = undef;
|
|||
my $bricks = undef;
|
||||
|
||||
my $gluster = which('gluster');
|
||||
my $lock = '/var/lock/gluster-zabbix.lock';
|
||||
|
||||
unless($gluster){
|
||||
# Gluster is not installed, exit with an error
|
||||
die "gluster command not found";
|
||||
}
|
||||
|
||||
# Get an exclusive lock
|
||||
open(LOCK, ">$lock") || die "Can't open $lock";
|
||||
flock(LOCK, 2);
|
||||
|
||||
GetOptions(
|
||||
"what=s" => \$what,
|
||||
|
@ -40,15 +44,14 @@ sub gluster($){
|
|||
my $code = 256;
|
||||
my @result = ();
|
||||
# Loop to run gluster cmd as it can fail if two run at the same time
|
||||
for (my $i = 0; ($code != 0 && $i < 10); $i++){
|
||||
open (RES, "$cmd |")
|
||||
for (my $i = 0; ($code != 0 && $i < 3); $i++){
|
||||
open (RES, "$cmd 2>/dev/null |")
|
||||
|| die "error: Could not execute $cmd";
|
||||
@result = <RES>;
|
||||
close RES;
|
||||
$code = $?;
|
||||
sleep(1) unless ($code == 0);
|
||||
}
|
||||
die "error: Could not execute $cmd" unless ($code == 0);
|
||||
return @result;
|
||||
}
|
||||
|
||||
|
@ -59,46 +62,85 @@ if (($what eq 'volume' && !$volume) ||
|
|||
}
|
||||
|
||||
if ($what eq 'volume'){
|
||||
my @volinfo = gluster("$gluster vol status $volume");
|
||||
my $bricksfound = 0;
|
||||
my $status = 'OK';
|
||||
my @volinfo = gluster("$gluster vol status $volume");
|
||||
unless (scalar @volinfo){
|
||||
die "Error occurred while trying to get volume status for $volume";
|
||||
}
|
||||
foreach my $line (@volinfo){
|
||||
# Check that all bricks are online
|
||||
if ($line =~ m/^Brick\ ([\w\.]+:\/[\w\.\/]+)\s+\d+\s+([A-Z])/){
|
||||
if ($line =~ m/^Brick\ ([\w\.]+:\/[\w\.\/]+)\s+\d+(\s+\d+)?\s+([A-Z])/){
|
||||
$bricksfound++;
|
||||
$status = "CRITICAL: brick status (reported $2 on $1)" if ($2 ne 'Y');
|
||||
if ($3 ne 'Y') {
|
||||
print "CRITICAL: brick status (reported $3 on $1)";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
# Check the Self-Heal daemons are up and running
|
||||
elsif ($line =~ m/^Self-heal\ Daemon\ on\ ([\w\.]+)\s+N\/A\\s+([A-Z])/){
|
||||
$status = "CRITICAL: self-heal daemon (reported $2 on $1)" if ($2 ne 'Y');
|
||||
elsif ($line =~ m/^Self-heal\ Daemon\ on\ ([\w\.]+)\s+N\/A\\s+([A-Z])/ && $2 ne 'Y'){
|
||||
print "CRITICAL: self-heal daemon (reported $2 on $1)";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
# Check the number of bricks is the one we expect
|
||||
if ($bricks && $bricks != $bricksfound){
|
||||
$status = "CRITICAL: bricks count mismatch (found $bricksfound while expecting $bricks)";
|
||||
print "CRITICAL: bricks count mismatch (found $bricksfound while expecting $bricks)";
|
||||
exit 1;
|
||||
}
|
||||
@volinfo = gluster("$gluster vol heal $volume info");
|
||||
unless (scalar @volinfo){
|
||||
die "Error occurred while trying to get volume heal info for $volume";
|
||||
}
|
||||
foreach my $line (@volinfo){
|
||||
if ($line =~ m/^Number\ of\ entries:\s+(\d+)$/ && $1 gt 0){
|
||||
# Lets check a second time to limit false positives
|
||||
sleep 1;
|
||||
@volinfo = gluster("$gluster vol heal $volume info");
|
||||
unless (scalar @volinfo){
|
||||
die "Error occurred while trying to get volume heal info for $volume";
|
||||
}
|
||||
foreach my $line (@volinfo){
|
||||
if ($line =~ m/^Number\ of\ entries:\s+(\d+)$/ && $1 gt 0){
|
||||
print "CRITICAL: self-heal in progress ($1)";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@volinfo = gluster("$gluster vol heal $volume info heal-failed");
|
||||
# the heal-failed command isn't supported on all version of GlusterFS
|
||||
if (scalar @volinfo){
|
||||
foreach my $line (@volinfo){
|
||||
# Now, check we don't have any file which the Self-Heal daemon couldn't sync
|
||||
if ($line =~ m/^Number\ of\ entries:\s+(\d+)$/){
|
||||
$status = "CRITICAL: self-heal error ($1)" if ($1 gt 0);
|
||||
if ($line =~ m/^Number\ of\ entries:\s+(\d+)$/ && $1 gt 0){
|
||||
print "CRITICAL: self-heal error ($1)";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@volinfo = gluster("$gluster vol heal $volume info split-brain");
|
||||
unless (scalar @volinfo){
|
||||
die "Error occurred while trying to get split-brain info for $volume";
|
||||
}
|
||||
foreach my $line (@volinfo){
|
||||
# Now, check we don't have any file in a split-brain situation
|
||||
if ($line =~ m/^Number\ of\ entries:\s+(\d+)$/){
|
||||
$status = "CRITICAL: split-bran ($1)" if ($1 gt 0);
|
||||
if ($line =~ m/^Number\ of\ entries:\s+(\d+)$/ && $1 gt 0){
|
||||
print "CRITICAL: split-bran ($1)";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
@volinfo = gluster("$gluster vol info $volume");
|
||||
unless (scalar @volinfo){
|
||||
die "Error occurred while trying to get volume info for $volume";
|
||||
}
|
||||
foreach my $line (@volinfo){
|
||||
# Check the volume is started
|
||||
if ($line =~ m/^Status:\s+(\w+)$/){
|
||||
$status = 'CRITICAL: The volume is not started' unless ($1 eq 'Started');
|
||||
if ($line =~ m/^Status:\s+(\w+)$/ && $1 ne 'Started'){
|
||||
print 'CRITICAL: The volume is not started';
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
print $status;
|
||||
print 'OK';
|
||||
}
|
||||
elsif ($what eq 'peer'){
|
||||
my @peers = gluster("$gluster pool list");
|
||||
|
@ -112,3 +154,5 @@ elsif ($what eq 'peer'){
|
|||
print $status;
|
||||
}
|
||||
|
||||
close(LOCK);
|
||||
exit(0);
|
||||
|
|
55
zabbix_scripts/check_httpd
Normal file
55
zabbix_scripts/check_httpd
Normal file
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use LWP::Simple;
|
||||
use Getopt::Long;
|
||||
use JSON;
|
||||
|
||||
my $uri = 'http://127.0.0.1/server-status';
|
||||
my $what = 'all';
|
||||
my $help = 0;
|
||||
|
||||
GetOptions(
|
||||
"uri=s" => \$uri,
|
||||
"what=s" => \$what,
|
||||
"help" => \$help
|
||||
);
|
||||
|
||||
my %res = ();
|
||||
my $status = get($uri . '?auto');
|
||||
|
||||
|
||||
unless ($status){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 1;
|
||||
}
|
||||
|
||||
foreach my $line (split(/\n/, $status)){
|
||||
next unless ($line =~ m/^(\w+(\s\w+)?):\s([\.\d]+)/);
|
||||
my ($key, $val) = ($1,$3);
|
||||
$key =~ s/\s/_/g;
|
||||
$key = lc $key;
|
||||
# Remove leading and trailing spaces
|
||||
$val =~ s/^\s+|\s+$//g;
|
||||
# Add 0 before the . when needed
|
||||
$val =~ s/^(\.\d+)$/0$1/;
|
||||
$res{$key} = $val;
|
||||
}
|
||||
|
||||
if ($help){
|
||||
print "Valid keys are:\n\n";
|
||||
print "$_\n" for keys %res;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($what eq 'all'){
|
||||
print to_json(\%res);
|
||||
}
|
||||
elsif (defined $res{$what}){
|
||||
print $res{$what};
|
||||
}
|
||||
else{
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
}
|
||||
exit 0;
|
45
zabbix_scripts/check_icmp_sudo
Normal file
45
zabbix_scripts/check_icmp_sudo
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
use JSON;
|
||||
|
||||
my $fping = which('fping');
|
||||
|
||||
unless ($fping){
|
||||
die "ZBX_NOTSUPPOTED\n";
|
||||
}
|
||||
|
||||
my $info = 'all';
|
||||
my $pretty = 0;
|
||||
my @valid_info = qw(all respond latency loss);
|
||||
my $host = $ARGV[0];
|
||||
|
||||
GetOptions(
|
||||
'info=s' => \$info,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
unless (grep { $info eq $_ } @valid_info){
|
||||
die "Usage: $0 [--info=<respond|latency|loss>] host\n";
|
||||
}
|
||||
|
||||
my $ping = qx($fping -c 5 -p 10 -q $host 2>&1);
|
||||
# Output looks like 10.29.254.2 : xmt/rcv/%loss = 5/5/0%, min/avg/max = 1.42/1.65/1.90
|
||||
if ($ping =~ m|^$host : xmt/rcv/%loss = 5/(\d)/(\d+(?:\.\d+)?)%(?:, min/avg/max = (?:\d+(?:\.\d+)?)/(\d+(\.\d+))/(?:\d+(?:\.\d+)?))?$|){
|
||||
my $stat = {
|
||||
respond => ($1 > 0) ? 1 : 0,
|
||||
loss => $2 + 0,
|
||||
latency => (defined $3) ? $3 / 1000 : 0
|
||||
};
|
||||
if ($info ne 'all'){
|
||||
print $stat->{$info} . "\n";
|
||||
} else {
|
||||
print to_json($stat, { pretty => $pretty }) . "\n";
|
||||
}
|
||||
} else {
|
||||
die "ZBX_NOTSUPPOTED\n";
|
||||
}
|
||||
exit 0;
|
|
@ -1,49 +1,76 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use Linux::LVM;
|
||||
use Zabbix::Agent::Addons::LVM;
|
||||
use Getopt::Long;
|
||||
use JSON;
|
||||
|
||||
Linux::LVM->units(B);
|
||||
Zabbix::Agent::Addons::LVM->units(B);
|
||||
|
||||
if (@ARGV < 2){
|
||||
usage();
|
||||
exit(1);
|
||||
my $vg = undef;
|
||||
my $lv = undef;
|
||||
my $what = undef;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'vg=s' => \$vg,
|
||||
'lv=s' => \$lv,
|
||||
'what:s' => \$what,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
if (not defined $lv and not defined $vg){
|
||||
$lv ||= $ARGV[0];
|
||||
$what ||= $ARGV[1];
|
||||
}
|
||||
|
||||
my $vol = $ARGV[0];
|
||||
my $what = $ARGV[1];
|
||||
if (not defined $lv and not defined $vg){
|
||||
usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
print<<"EOF";
|
||||
|
||||
Usage: $0 <logical volume> [size|allocation|allocation_pool_data|allocation_metadata|status]
|
||||
$0 --lv=<logical volume>
|
||||
$0 --lv=<logical volume> --what=<size|allocation|allocation_pool_data|allocation_metadata|status|etc.>
|
||||
$0 --vg=<volume group>
|
||||
$0 --vg=<volume group> --what=<alloc_pe_size|vg_size|etc.>
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
my %info = get_lv_info($vol);
|
||||
|
||||
if ($what eq 'size'){
|
||||
print $info{size};
|
||||
}
|
||||
elsif ($what eq 'allocation'){
|
||||
my $ret = (defined $info{allocated_to_snapshot}) ? $info{allocated_to_snapshot} : "ZBX_NOTSUPPORTED";
|
||||
$ret =~ s/,/\./;
|
||||
print $ret;
|
||||
}
|
||||
elsif ($what eq 'allocation_pool_data'){
|
||||
my $ret = (defined $info{allocated_pool_data}) ? $info{allocated_pool_data} : "ZBX_NOTSUPPORTED";
|
||||
$ret =~ s/,/\./;
|
||||
print $ret;
|
||||
}
|
||||
elsif ($what eq 'allocation_metadata'){
|
||||
my $ret = (defined $info{allocated_meta_data}) ? $info{allocated_meta_data} : "ZBX_NOTSUPPORTED";
|
||||
$ret =~ s/,/\./;
|
||||
print $ret;
|
||||
}
|
||||
elsif ($what eq 'status'){
|
||||
print $info{status};
|
||||
}
|
||||
else{
|
||||
my $json;
|
||||
if (defined $vg){
|
||||
%{$json} = get_volume_group_information($vg);
|
||||
# Depending on LVM version, alloc_ct might not be present
|
||||
if (not defined $json->{alloc_ct}){
|
||||
$json->{alloc_ct} = sprintf("%.1f", 100 * $json->{alloc_pe_size} / $json->{vg_size});
|
||||
}
|
||||
} elsif (defined $lv) {
|
||||
%{$json} = get_lv_info($lv);
|
||||
} else{
|
||||
usage();
|
||||
}
|
||||
|
||||
# Normalize float values
|
||||
foreach (qw(allocated_to_snapshot allocated_pool_data allocated_meta_data)){
|
||||
$json->{$_} =~ s/,/./g if (defined $json->{$_});
|
||||
}
|
||||
# Compat with older versions
|
||||
my $old_keys = {
|
||||
allocation => 'allocated_to_snapshot',
|
||||
allocation_pool_data => 'allocated_pool_data',
|
||||
allocation_metadata => 'allocated_meta_data'
|
||||
};
|
||||
if (defined $what && defined $old_keys->{$what}){
|
||||
$what = $old_keys->{$what};
|
||||
}
|
||||
|
||||
if (defined $what and $what ne ''){
|
||||
print ((defined $json->{$what}) ? $json->{$what} : 'ZBX_NOTSUPPOTED');
|
||||
} else {
|
||||
print to_json($json, { pretty => $pretty });
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
|
125
zabbix_scripts/check_mpath_sudo
Normal file
125
zabbix_scripts/check_mpath_sudo
Normal file
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
|
||||
my $json = {};
|
||||
my $mpath = undef;
|
||||
my $help = 0;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"mpath=s" => \$mpath,
|
||||
"help" => \$help,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
my $multipathd = which('multipathd');
|
||||
|
||||
if (not defined $multipathd){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($help or not defined $mpath){
|
||||
print <<_EOF;
|
||||
Usage : $0 --mpath=<name of the mpath device> [--pretty]
|
||||
|
||||
* --mpath : the name of the device to check
|
||||
* --pretty : output pretty JSON, easier to read for humans
|
||||
* --help : display this help
|
||||
|
||||
_EOF
|
||||
exit 2;
|
||||
}
|
||||
|
||||
$json = {
|
||||
mpath => $mpath,
|
||||
size => 0,
|
||||
dm_st => 'unknown',
|
||||
features => '',
|
||||
failures => 0,
|
||||
path_failures => 0,
|
||||
paths_num_total => 0,
|
||||
paths_num_ko => 0,
|
||||
paths_num_active => 0,
|
||||
paths_num_inactive => 0,
|
||||
paths_details => [],
|
||||
paths_with_issue => [],
|
||||
errors => []
|
||||
};
|
||||
my @res = qx($multipathd show maps raw format "%n|%N|%S|%f|%t|%x|%0");
|
||||
if ($? != 0){
|
||||
push @{$json->{errors}}, "Failed to run multipathd show maps raw format";
|
||||
}
|
||||
foreach (@res){
|
||||
chomp;
|
||||
next if $_ !~ /^$mpath\|/;
|
||||
(undef, $json->{paths_num_total}, $json->{size}, $json->{features},
|
||||
$json->{dm_st}, $json->{failures}, $json->{path_failures}) = split(/\s*\|\s*/, $_);
|
||||
# Cast to int
|
||||
foreach (qw(failures path_failures paths_num_total)){
|
||||
$json->{$_} = 0 + $json->{$_};
|
||||
}
|
||||
# Convert size to bytes
|
||||
my $unit = chop $json->{size};
|
||||
if ($unit eq 'K'){
|
||||
$json->{size} *= 1024;
|
||||
} elsif ($unit eq 'M'){
|
||||
$json->{size} *= 1024 * 1024;
|
||||
} elsif ($unit eq 'G'){
|
||||
$json->{size} *= 1024 * 1024 * 1024;
|
||||
} elsif ($unit eq 'T'){
|
||||
$json->{size} *= 1024 * 1024 * 1024 * 1024;
|
||||
} elsif ($unit eq 'P'){
|
||||
$json->{size} *= 1024 * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
# No need to process the other mpath here
|
||||
last;
|
||||
}
|
||||
|
||||
# Now check status of every path
|
||||
@res = qx($multipathd show paths format "%m|%d|%t|%o|%T|%0|%z");
|
||||
if ($? != 0){
|
||||
push @{$json->{errors}}, "Failed to run multipathd show paths format";
|
||||
}
|
||||
# Skip header line
|
||||
shift @res;
|
||||
foreach (@res){
|
||||
chomp;
|
||||
next if $_ !~ /^$mpath\|/;
|
||||
my (undef, $dev, $dm_st, $dev_st, $chk_st, $failures, $serial) = split(/\s*\|\s*/, $_);
|
||||
push @{$json->{paths_details}}, {
|
||||
dev => $dev,
|
||||
dm_st => $dm_st,
|
||||
dev_st => $dev_st,
|
||||
chk_st => $chk_st,
|
||||
failures => $failures + 0,
|
||||
serial => $serial
|
||||
};
|
||||
if ($dm_st eq 'active'){
|
||||
$json->{paths_num_active} += 1;
|
||||
if ($dev_st ne 'running'){
|
||||
$json->{paths_num_ko} += 1;
|
||||
push @{$json->{paths_with_issue}}, $dev;
|
||||
push @{$json->{errors}}, "dev $dev is not running";
|
||||
} elsif ($chk_st ne 'ready' or $failures > 0){
|
||||
$json->{paths_num_ko} += 1;
|
||||
push @{$json->{paths_with_issue}}, $dev;
|
||||
push @{$json->{errors}}, "dev $dev is not active";
|
||||
} else {
|
||||
$json->{paths_num_ok} += 1;
|
||||
}
|
||||
} else {
|
||||
$json->{paths_num_inactive} += 1;
|
||||
}
|
||||
}
|
||||
# We want easy usage from zabbix, so turn thos ones to strings
|
||||
$json->{paths_with_issue} = join(',', @{$json->{paths_with_issue}});
|
||||
$json->{errors} = join(',', @{$json->{errors}});
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
||||
exit 0;
|
109
zabbix_scripts/check_mysql_sudo
Normal file
109
zabbix_scripts/check_mysql_sudo
Normal file
|
@ -0,0 +1,109 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Data::Dumper;
|
||||
use Getopt::Long;
|
||||
|
||||
my $what = 'all';
|
||||
my $defaults = undef;
|
||||
my $host = undef;
|
||||
my $port = undef;
|
||||
my $user = undef;
|
||||
my $password = undef;
|
||||
my $help = 0;
|
||||
my $pretty = 0;
|
||||
my $exit = 0;
|
||||
|
||||
my $json = {
|
||||
zbx_error => "none"
|
||||
};
|
||||
|
||||
GetOptions(
|
||||
"what=s" => \$what,
|
||||
"help" => \$help,
|
||||
"defaults=s" => \$defaults,
|
||||
"host=s" => \$host,
|
||||
"port=s" => \$port,
|
||||
"user=s" => \$user,
|
||||
"password=s" => \$password,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
# Basic input checks
|
||||
if (defined $defaults and $defaults ne '' and not -e $defaults){
|
||||
$json->{zbx_error} = "File $defaults doesn't exist";
|
||||
$exit = 1;
|
||||
} elsif (defined $host and $host ne '' and $host !~ m/^[\w\-\.]+$/){
|
||||
$json->{zbx_error} = "Bad value for --host";
|
||||
$exit = 1;
|
||||
} elsif (defined $port and $port ne '' and ($port !~ m/^\d+$/ or $port lt 1 or $port gt 65535)){
|
||||
$json->{zbx_error} = "Bad value for --port";
|
||||
$exit = 1;
|
||||
} elsif (defined $user and $user ne '' and $user !~ m/^[\w\-\.]+$/){
|
||||
$json->{zbx_error} = "Bad value for --user";
|
||||
$exit = 1;
|
||||
} elsif (defined $password and $password ne '') {
|
||||
# Just escape quotes as will protect the password with
|
||||
$password =~ s/'/\\'/g;
|
||||
}
|
||||
|
||||
if ($help){
|
||||
print <<_EOF;
|
||||
Usage: $0 [--what=key] [--help] [--pretty]
|
||||
|
||||
* --what : if a key is given (eg --what=Bytes_received) will print only this value.
|
||||
Else, all the stats are printed in a json format.
|
||||
Run once without --what to get a list of available keys
|
||||
|
||||
* --help : print this help and exit
|
||||
|
||||
* --defaults : set the file from which mysql will read defaults
|
||||
|
||||
* --host : set the hostname to connect to
|
||||
|
||||
* --user : set the user to connect as
|
||||
|
||||
* --password : set the password to use
|
||||
|
||||
* --pretty : prints JSON in a pretty, human readable format. Has no use when --what is also given
|
||||
_EOF
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($exit eq 0){
|
||||
my $opt = "";
|
||||
$opt .= " --defaults-file=$defaults" if (defined $defaults and $defaults ne '');
|
||||
$opt .= " --host=$host" if (defined $host and $host ne '');
|
||||
$opt .= " --user=$user" if (defined $user and $user ne '');
|
||||
$opt .= " --password='$password'" if (defined $password and $password ne '');
|
||||
my @status = qx(mysql $opt --batch --execute 'show global status;' 2>&1);
|
||||
if ($? != 0){
|
||||
$exit = $?;
|
||||
$json->{zbx_error} = join '', @status;
|
||||
} else {
|
||||
foreach (@status){
|
||||
chomp;
|
||||
my ($key, $val) = split(/\t/, $_);
|
||||
$json->{$key} = $val;
|
||||
}
|
||||
# Some older MySQL do not have all the variables we might want
|
||||
if (not defined $json->{Acl_users}){
|
||||
$json->{Acl_users} = qx(mysql $opt --batch --skip-column-names --execute 'select count(user) from user;' mysql);
|
||||
chomp $json->{Acl_users};
|
||||
}
|
||||
if (not defined $json->{Max_statement_time_exceeded} and defined $json->{Max_execution_time_exceeded}){
|
||||
$json->{Max_statement_time_exceeded} = $json->{Max_execution_time_exceeded}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($what ne 'all' and defined $json->{$what}){
|
||||
print $json->{$what} . "\n";
|
||||
} else {
|
||||
print to_json($json, { pretty => $pretty });
|
||||
}
|
||||
|
||||
exit $exit;
|
||||
|
56
zabbix_scripts/check_nginx
Executable file
56
zabbix_scripts/check_nginx
Executable file
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use LWP::Simple;
|
||||
use Getopt::Long;
|
||||
use JSON;
|
||||
|
||||
my $uri = 'http://127.0.0.1/nginx-status';
|
||||
my $what = 'all';
|
||||
my $help = 0;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"uri=s" => \$uri,
|
||||
"what=s" => \$what,
|
||||
"help" => \$help,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
my $res = {};
|
||||
my $status = get($uri);
|
||||
|
||||
|
||||
unless ($status){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 1;
|
||||
}
|
||||
|
||||
foreach my $line (split(/\n/, $status)){
|
||||
if ($line =~ m/^Active connections: (\d+)/){
|
||||
$res->{active_connections} = $1;
|
||||
} elsif ($line =~ m/\s*(\d+)\s+\d+\s+(\d+)/){
|
||||
$res->{total_connections} = $1;
|
||||
$res->{total_requests} = $2;
|
||||
} elsif ($line =~ m/Waiting: (\d+)/){
|
||||
$res->{keep_alive} = $1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($help){
|
||||
print "Valid keys are:\n\n";
|
||||
print "$_\n" for keys %{$res};
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($what eq 'all'){
|
||||
print to_json($res, { pretty => $pretty });
|
||||
}
|
||||
elsif (defined $res->{$what}){
|
||||
print $res->{$what};
|
||||
}
|
||||
else{
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
}
|
||||
exit 0;
|
104
zabbix_scripts/check_pmg_sudo
Normal file
104
zabbix_scripts/check_pmg_sudo
Normal file
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
use PMG::DBTools;
|
||||
|
||||
my $json = {
|
||||
count_in => 0,
|
||||
count_out => 0,
|
||||
bytes_in => 0,
|
||||
bytes_out => 0,
|
||||
spam_in => 0,
|
||||
spam_out => 0,
|
||||
virus_in => 0,
|
||||
virus_out => 0,
|
||||
ptime_in => 0,
|
||||
ptime_out => 0,
|
||||
queue_hold => 0,
|
||||
queue_active => 0,
|
||||
queue_deferred => 0
|
||||
};
|
||||
my $pretty = 0;
|
||||
my ($domain,$what) = undef;
|
||||
my $timespan = 900;
|
||||
my $spamthres = 5;
|
||||
my $resp = undef;
|
||||
|
||||
GetOptions(
|
||||
'domain=s' => \$domain,
|
||||
'what=s' => \$what,
|
||||
'timespan=i' => \$timespan,
|
||||
'spamthres=i' => \$spamthres,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $dbh = PMG::DBTools::open_ruledb;
|
||||
|
||||
my $since = time - $timespan;
|
||||
my $query = "SELECT cstatistic.direction AS direction, cstatistic.bytes AS bytes, cstatistic.spamlevel AS spamlevel, " .
|
||||
"cstatistic.virusinfo AS virus, cstatistic.ptime AS ptime, cstatistic.sender AS sender, creceivers.receiver " .
|
||||
"AS receiver FROM cstatistic LEFT JOIN creceivers ON cstatistic.rid = creceivers.cstatistic_rid" .
|
||||
" WHERE time > ?";
|
||||
my $sth = $dbh->prepare($query);
|
||||
$sth->execute($since);
|
||||
|
||||
while (my $res = $sth->fetchrow_hashref){
|
||||
if (not $res->{direction}){
|
||||
next if (defined $domain and $res->{sender} !~ m/.*\@$domain$/);
|
||||
$json->{bytes_out} += $res->{bytes};
|
||||
$json->{count_out} += 1;
|
||||
$json->{ptime_out} += $res->{ptime};
|
||||
$json->{spam_out} += 1 if ($res->{spamlevel} ge $spamthres);
|
||||
$json->{virus_out} += 1 if (defined $res->{virus});
|
||||
} else {
|
||||
next if (defined $domain and $res->{receiver} !~ /.*\@$domain$/);
|
||||
$json->{bytes_in} += $res->{bytes};
|
||||
$json->{count_in} += 1;
|
||||
$json->{ptime_in} += $res->{ptime};
|
||||
$json->{spam_in} += 1 if ($res->{spamlevel} ge $spamthres);
|
||||
$json->{virus_in} += 1 if (defined $res->{virus});
|
||||
}
|
||||
}
|
||||
|
||||
# Init to 0 if missing
|
||||
$json->{$_} //= 0 foreach (qw/bytes_out count_out ptime_out spam_out virus_out
|
||||
bytes_in count_in ptime_in spam_in virus_in/);
|
||||
|
||||
# Compute averages
|
||||
$json->{ptime_in} = $json->{ptime_in} / $json->{count_in} / 1000 if ($json->{count_in} > 0);
|
||||
$json->{ptime_out} = $json->{ptime_out} / $json->{count_out} / 1000 if ($json->{count_out} > 0);
|
||||
|
||||
# Now, only for general stats, count early rejects, and queue stats
|
||||
if (not defined $domain){
|
||||
$query = "SELECT SUM(rblcount) AS rbl, SUM(pregreetcount) AS pregreet FROM localstat WHERE mtime > ?";
|
||||
$sth = $dbh->prepare($query);
|
||||
$sth->execute($since);
|
||||
my $res = $sth->fetchrow_hashref;
|
||||
$json->{$_} = $res->{$_} foreach (qw/rbl pregreet/);
|
||||
|
||||
# Here we count email in the queue (active, deferred and hold queues)
|
||||
foreach my $res (qx(postqueue -j)){
|
||||
$res = from_json($res);
|
||||
foreach (qw/hold active deferred/){
|
||||
$json->{'queue_' . $_} += 1 if ($res->{queue_name} eq $_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$json->{$_} //= 0 foreach (qw/rbl pregreet/);
|
||||
|
||||
if (defined $what and not defined $json->{$what}){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 0;
|
||||
} elsif (defined $what){
|
||||
$resp = $json->{$what}
|
||||
} else {
|
||||
$resp = $json;
|
||||
}
|
||||
$resp = (ref $resp eq 'HASH' or ref $resp eq 'ARRAY') ? to_json($resp, { pretty => $pretty }) : $resp;
|
||||
print $resp . "\n";
|
||||
|
182
zabbix_scripts/check_pve_sudo
Normal file
182
zabbix_scripts/check_pve_sudo
Normal file
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
use File::Path qw(make_path);
|
||||
use File::Basename;
|
||||
use Data::Dumper;
|
||||
|
||||
my $pvesh = which('pvesh');
|
||||
my $json = {};
|
||||
my $pretty = 0;
|
||||
my ($cluster,$guest,$node,$storage,$pool) = undef;
|
||||
|
||||
# Max age of cached values
|
||||
my $cache = 60;
|
||||
my $cache_dir = '/tmp/zbx_pve_cache/';
|
||||
|
||||
GetOptions(
|
||||
'cluster' => \$cluster,
|
||||
'guest=i' => \$guest,
|
||||
'node=s' => \$node,
|
||||
'storage=s' => \$storage,
|
||||
'pool=s' => \$pool,
|
||||
'pretty' => \$pretty,
|
||||
'cache=i' => \$cache,
|
||||
'cache-dir=s' => \$cache_dir
|
||||
);
|
||||
|
||||
# Old versions do not support, nore need --output-format=json
|
||||
my $pvesh_opt = (system("$pvesh ls / --output-format=json 2>&1 > /dev/null") == 0) ? '--output-format=json' : '';
|
||||
|
||||
if ($cluster){
|
||||
my $cluster = get_api_data('/cluster/status');
|
||||
# Set default values so monitoring works for single node, without cluster setup
|
||||
$json->{status} = {
|
||||
all_online => 1,
|
||||
quorate => 1,
|
||||
nodes => 1,
|
||||
name => 'default',
|
||||
version => 1
|
||||
};
|
||||
# Set default global stats
|
||||
$json->{network} = {
|
||||
in => 0,
|
||||
out => 0
|
||||
};
|
||||
$json->{disk} = {
|
||||
read => 0,
|
||||
write => 0
|
||||
};
|
||||
$json->{guests} = {
|
||||
qemu => 0,
|
||||
qemu_running => 0,
|
||||
lxc => 0,
|
||||
lxc_running => 0
|
||||
};
|
||||
my @nodes = ();
|
||||
foreach my $item (@{$cluster}){
|
||||
if ($item->{type} eq 'cluster'){
|
||||
$json->{status}->{$_} = $item->{$_} foreach (qw(quorate nodes name version));
|
||||
} elsif ($item->{type} eq 'node' and $item->{online}){
|
||||
push @nodes, $item->{name};
|
||||
} elsif ($item->{type} eq 'node'){
|
||||
$json->{status}->{all_online} = 0;
|
||||
}
|
||||
}
|
||||
foreach my $node (@nodes){
|
||||
my $n = get_api_data("/nodes/$node/status");
|
||||
# Here we gather (and sum) some info about individual nodes to get the total number of
|
||||
# CPU, the amount of memory etc...
|
||||
$json->{memory}->{$_} += $n->{memory}->{$_} foreach (qw(free total used));
|
||||
$json->{ksm}->{$_} += $n->{ksm}->{$_} foreach (qw(shared));
|
||||
$json->{cpuinfo}->{$_} += $n->{cpuinfo}->{$_} foreach (qw(cpus sockets));
|
||||
$json->{loadavg}[$_] += $n->{loadavg}[$_] foreach (0..2);
|
||||
}
|
||||
# We want average load avg of the cluster, not the sum of individual loads
|
||||
$json->{loadavg}[$_] = sprintf "%.2f", $json->{loadavg}[$_] / $json->{status}->{nodes} foreach (0..2);
|
||||
|
||||
my $guests = get_api_data('/cluster/resources', '--type=vm');
|
||||
foreach my $guest (@{$guests}){
|
||||
$json->{network}->{in} += $guest->{netin} || 0;
|
||||
$json->{network}->{out} += $guest->{netout} || 0;
|
||||
$json->{disk}->{read} += $guest->{diskread} || 0;
|
||||
$json->{disk}->{write} += $guest->{diskwrite} || 0;
|
||||
my $type = $guest->{type};
|
||||
$json->{guests}->{$type}++;
|
||||
$json->{guests}->{$type . '_running'}++ if ($guest->{status} eq 'running');
|
||||
}
|
||||
} elsif ($node){
|
||||
$json->{guests} = {
|
||||
qemu => 0,
|
||||
qemu_running => 0,
|
||||
lxc => 0,
|
||||
lxc_running => 0
|
||||
};
|
||||
foreach my $item (qw(status version subscription)){
|
||||
$json->{$item} = get_api_data("/nodes/$node/$item");
|
||||
}
|
||||
my $guests = get_api_data('/cluster/resources', '--type=vm');
|
||||
foreach my $guest (@{$guests}){
|
||||
next if ($guest->{node} ne $node);
|
||||
my $type = $guest->{type};
|
||||
$json->{guests}->{$type}++;
|
||||
$json->{guests}->{$type . '_running'}++ if ($guest->{status} eq 'running');
|
||||
}
|
||||
} elsif ($guest){
|
||||
my $guests = get_api_data('/cluster/resources', '--type=vm');
|
||||
foreach my $g (@{$guests}){
|
||||
if ($g->{vmid} eq $guest){
|
||||
$json = $g;
|
||||
last;
|
||||
}
|
||||
}
|
||||
} elsif ($pool){
|
||||
my $pool = get_api_data("/pools/$pool");
|
||||
$json->{comment} = $pool->{comment};
|
||||
foreach my $type (qw(qemu lxc)){
|
||||
$json->{$_}->{$type} = 0 foreach (qw(guests templates));
|
||||
}
|
||||
foreach my $item (@{$pool->{members}}){
|
||||
if ($item->{type} =~ m/^(qemu|lxc)$/ and !$item->{template}){
|
||||
$json->{guests}->{$_} += $item->{$_} foreach (qw(maxcpu diskread diskwrite maxdisk mem maxmem netin netout));
|
||||
$json->{guests}->{used_cpu} += $item->{cpu} * $item->{maxcpu};
|
||||
$json->{guests}->{$item->{type}}++;
|
||||
}
|
||||
if ($item->{type} =~ m/^(qemu|lxc)$/ and $item->{template}){
|
||||
$json->{templates}->{$_} += $item->{$_} foreach (qw(maxdisk));
|
||||
$json->{templates}->{$item->{type}}++;
|
||||
}
|
||||
}
|
||||
$json->{guests}->{$_} //= 0 foreach (qw(cpu maxcpu diskread diskwrite maxdisk mem maxmem netin netout));
|
||||
$json->{templates}->{$_} //= 0 foreach (qw(maxdisk));
|
||||
$json->{guests}->{cpu} = ($json->{guests}->{maxcpu} == 0) ? 0 : $json->{guests}->{used_cpu} / $json->{guests}->{maxcpu};
|
||||
} elsif ($storage){
|
||||
my $stores = get_api_data('/cluster/resources', '--type=storage');
|
||||
foreach my $s (@{$stores}){
|
||||
if ($s->{storage} eq $storage){
|
||||
$json->{maxdisk} = $s->{maxdisk};
|
||||
$json->{disk} = $s->{disk};
|
||||
last;
|
||||
}
|
||||
}
|
||||
} else{
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 0;
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
||||
|
||||
# Helper which will either get data from
|
||||
# the cache if its fresh enough, or query the API
|
||||
# and save the result in the cache for later
|
||||
sub get_api_data {
|
||||
my ($path, $query_opt) = @_;
|
||||
$query_opt ||= '';
|
||||
my $opt_filename = $query_opt;
|
||||
$opt_filename =~ s/[\-=]/_/g;
|
||||
my $res;
|
||||
# Is the cache existing and fresh enough ?
|
||||
if (-f $cache_dir . $path . $opt_filename and int((-M $cache_dir . $path . $opt_filename)*60*60*24) < $cache){
|
||||
{
|
||||
local $/; # Enable slurp
|
||||
open my $fh, "<", $cache_dir . $path . $opt_filename;
|
||||
$res = <$fh>;
|
||||
close $fh;
|
||||
}
|
||||
} else {
|
||||
$res = qx($pvesh get $path $query_opt $pvesh_opt 2>/dev/null);
|
||||
# Save the result in the cache for later retrival
|
||||
eval{
|
||||
my $dir = (fileparse($path))[1];
|
||||
make_path($cache_dir . $dir, { chmod => 700 });
|
||||
};
|
||||
open my $fh, ">", $cache_dir . $path . $opt_filename;
|
||||
print $fh $res;
|
||||
close $fh;
|
||||
}
|
||||
return from_json($res);
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
|
||||
my $slot = '';
|
||||
my $hpacucli = '/usr/sbin/hpacucli';
|
||||
my $cli = which('hpacucli') || which('ssacli');
|
||||
my @validchecks = qw/controller array logicaldrive physicaldrive/;
|
||||
my $check = join ',', @validchecks;
|
||||
|
||||
|
@ -19,7 +20,7 @@ $0 --slot=<slot number> --check=<what to check>
|
|||
|
||||
* slot must be a number. You can find on which slot you have controllers with the command:
|
||||
|
||||
$hpacucli controller all show status
|
||||
$cli controller all show status
|
||||
|
||||
* check is a comma separated list of item to check. Default values (without --check option) will check everything
|
||||
Valid values are:
|
||||
|
@ -34,8 +35,8 @@ if ($slot !~ /^\d+$/){
|
|||
usage();
|
||||
}
|
||||
|
||||
unless (-x $hpacucli){
|
||||
die "Cannot run $hpacucli\n";
|
||||
unless (-x $cli){
|
||||
die "Cannot run $cli\n";
|
||||
}
|
||||
|
||||
my @checks = split /\s?,\s?/, $check;
|
||||
|
@ -46,9 +47,9 @@ foreach my $check (@checks){
|
|||
foreach my $param (@checks){
|
||||
# Global controller checks
|
||||
if ($param eq 'controller'){
|
||||
open HPACUCLI, "$hpacucli controller slot=$slot show status|" ||
|
||||
die "An error occured while running $hpacucli: $!";
|
||||
foreach my $line (<HPACUCLI>){
|
||||
open CLI, "$cli controller slot=$slot show status|" ||
|
||||
die "An error occured while running $cli: $!";
|
||||
foreach my $line (<CLI>){
|
||||
if ( $line =~ /Status\:\s*([\w\s]+)$/ ) {
|
||||
my $res = $1;
|
||||
chomp($res);
|
||||
|
@ -58,12 +59,12 @@ foreach my $param (@checks){
|
|||
}
|
||||
}
|
||||
}
|
||||
close HPACUCLI;
|
||||
close CLI;
|
||||
}
|
||||
else{
|
||||
open HPACUCLI, "$hpacucli controller slot=$slot $param all show status|" ||
|
||||
die "An error occured while running $hpacucli: $!";
|
||||
foreach my $line (<HPACUCLI>){
|
||||
open CLI, "$cli controller slot=$slot $param all show status|" ||
|
||||
die "An error occured while running $cli: $!";
|
||||
foreach my $line (<CLI>){
|
||||
if ( $line =~ /^\s*$param.*:\s*(\w+[\w\s]*)$/i ) {
|
||||
my $res = $1;
|
||||
chomp($res);
|
||||
|
@ -73,7 +74,7 @@ foreach my $param (@checks){
|
|||
}
|
||||
}
|
||||
}
|
||||
close HPACUCLI;
|
||||
close CLI;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,16 +31,15 @@ my $file = "/proc/mdstat";
|
|||
my $device = "all";
|
||||
|
||||
# Get command line options.
|
||||
GetOptions ('file=s' => \$file,
|
||||
GetOptions (
|
||||
'file=s' => \$file,
|
||||
'device=s' => \$device,
|
||||
'help' => sub { &usage() } );
|
||||
'help' => sub { &usage() }
|
||||
);
|
||||
|
||||
## Strip leading "/dev/" from --device in case it has been given
|
||||
$device =~ s/^\/dev\///;
|
||||
|
||||
## Return codes for Nagios
|
||||
my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);
|
||||
|
||||
## This is a global return value - set to the worst result we get overall
|
||||
my $retval = 0;
|
||||
|
||||
|
@ -68,23 +67,35 @@ while (<FILE>) {
|
|||
}
|
||||
elsif ($2 eq "(S)") {
|
||||
$spare_devs{$dev} .= "$1,";
|
||||
$devs_up++;
|
||||
}
|
||||
else {
|
||||
$active_devs{$dev} .= "$1,";
|
||||
$devs_up++;
|
||||
}
|
||||
}
|
||||
if (! defined($active_devs{$dev})) { $active_devs{$dev} = "none"; }
|
||||
else { $active_devs{$dev} =~ s/,$//; }
|
||||
if (! defined($spare_devs{$dev})) { $spare_devs{$dev} = "none"; }
|
||||
else { $spare_devs{$dev} =~ s/,$//; }
|
||||
if (! defined($failed_devs{$dev})) { $failed_devs{$dev} = "none"; }
|
||||
else { $failed_devs{$dev} =~ s/,$//; }
|
||||
if (! defined($active_devs{$dev})){
|
||||
$active_devs{$dev} = "none";
|
||||
}
|
||||
else {
|
||||
$active_devs{$dev} =~ s/,$//;
|
||||
}
|
||||
if (! defined($spare_devs{$dev})){
|
||||
$spare_devs{$dev} = "none";
|
||||
}
|
||||
else {
|
||||
$spare_devs{$dev} =~ s/,$//;
|
||||
}
|
||||
if (! defined($failed_devs{$dev})){
|
||||
$failed_devs{$dev} = "none";
|
||||
}
|
||||
else {
|
||||
$failed_devs{$dev} =~ s/,$//;
|
||||
}
|
||||
|
||||
$_ = <FILE>;
|
||||
/(\d+)\ blocks\ (.*)(\[.*\])\s?$/;
|
||||
$size{$dev} = int($1/1024);
|
||||
#print "$3\n";
|
||||
$missing = 1 if ($3 =~ m/_/);
|
||||
if ($size{$dev} > 1024){
|
||||
$size{$dev} = int($size{$dev}/1024)."GB";
|
||||
|
@ -93,23 +104,20 @@ while (<FILE>) {
|
|||
$size{$dev} .= "MB";
|
||||
}
|
||||
$_ = <FILE>;
|
||||
|
||||
if (($devs_total{$dev} > $devs_up) || ($failed_devs{$dev} ne "none") || (($missing) && (!/recovery/))) {
|
||||
$status{$dev} = "Degraded";
|
||||
$result = "CRITICAL";
|
||||
$retval = $ERRORS{"CRITICAL"};
|
||||
}
|
||||
else {
|
||||
$status{$dev} = "Optimal";
|
||||
}
|
||||
if (/recovery/){
|
||||
if (/(recovery|resync)\s*=\s*\d{1,2}(\.\d)?%/){
|
||||
$status{$dev} = "Rebuilding";
|
||||
if ($result eq "OK"){
|
||||
$result = "WARNING";
|
||||
$retval = $ERRORS{"WARNING"};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
print "$result: ";
|
||||
foreach my $raid (@raids){
|
||||
|
@ -117,11 +125,10 @@ foreach my $raid (@raids){
|
|||
}
|
||||
print "\n";
|
||||
close FILE;
|
||||
exit $retval;
|
||||
exit 0;
|
||||
|
||||
# =====
|
||||
sub usage()
|
||||
{
|
||||
sub usage(){
|
||||
printf("
|
||||
Check status of Linux SW RAID
|
||||
|
||||
|
|
|
@ -125,6 +125,23 @@ ADAPTER: for ( my $adp = 0; $adp < $adapters; $adp++ ) {
|
|||
}
|
||||
close LDGETNUM;
|
||||
|
||||
open (CFGDSPLY, "$megacli -CfgDsply -a$adp -NoLog |")
|
||||
|| die "error: Could not execute $megacli -CfgDsply -a$adp -NoLog";
|
||||
|
||||
my $hba = 0;
|
||||
my $failgrouplist = 0;
|
||||
while (<CFGDSPLY>) {
|
||||
if ( m/Failed to get Disk Group list/ ) {
|
||||
$failgrouplist = 1;
|
||||
}
|
||||
if ( m/Product Name:.*(JBOD|HBA)/ ) {
|
||||
$hba = 1;
|
||||
}
|
||||
}
|
||||
close CFGDSPLY;
|
||||
|
||||
# When controller is in HBA/JBOD mode, skip RAID volume checks
|
||||
unless ($hba && $failgrouplist) {
|
||||
LDISK: for ( my $ld = 0; $ld < $ldnum; $ld++ ) {
|
||||
# Get info on this particular logical drive
|
||||
open (LDINFO, "$megacli -LdInfo -L$ld -a$adp -NoLog |")
|
||||
|
@ -140,7 +157,7 @@ ADAPTER: for ( my $adp = 0; $adp < $adapters; $adp++ ) {
|
|||
$size = sprintf( "%.0f", ($size / 1024) );
|
||||
$unit= 'GB';
|
||||
}
|
||||
} elsif ( m/^State\s*:\s*(\w+)/ ) {
|
||||
} elsif ( m/^State\s*:\s*(\w+(\s\w+)?)/ ) {
|
||||
$state = $1;
|
||||
if ( $state ne 'Optimal' ) {
|
||||
$status = 'CRITICAL';
|
||||
|
@ -160,12 +177,13 @@ ADAPTER: for ( my $adp = 0; $adp < $adapters; $adp++ ) {
|
|||
|
||||
} #LDISK
|
||||
close LDINFO;
|
||||
}
|
||||
|
||||
# Get info on physical disks for this adapter
|
||||
open (PDLIST, "$megacli -PdList -a$adp -NoLog |")
|
||||
|| die "error: Could not execute $megacli -PdList -a$adp -NoLog";
|
||||
|
||||
my ($slotnumber,$fwstate);
|
||||
my ($slotnumber,$fwstate,$fwinfo);
|
||||
PDISKS: while (<PDLIST>) {
|
||||
if ( m/Slot Number:\s*(\d+)/ ) {
|
||||
$slotnumber = $1;
|
||||
|
@ -180,12 +198,15 @@ ADAPTER: for ( my $adp = 0; $adp < $adapters; $adp++ ) {
|
|||
}
|
||||
} elsif ( m/Predictive Failure Count:\s*(\d+)/ ) {
|
||||
$prederrors += $1;
|
||||
} elsif ( m/Firmware state:\s*(\w+)/ ) {
|
||||
} elsif ( m/Firmware state:\s*(\w+)(.*)/ ) {
|
||||
$fwstate = $1;
|
||||
$fwinfo = $2;
|
||||
if ( $fwstate =~ m/Hotspare/ ) {
|
||||
$hotsparecount++;
|
||||
} elsif ( $fwstate =~ m/^Online/ ) {
|
||||
# Do nothing
|
||||
} elsif ( $fwstate =~ m/^Unconfigured/ && defined $fwinfo && $fwinfo =~ m/^\(good\)/) {
|
||||
# Do nothing
|
||||
} elsif ( $slotnumber != 255 ) {
|
||||
$pdbad++;
|
||||
$status = 'CRITICAL';
|
||||
|
|
46
zabbix_scripts/check_sa_learn_sudo
Normal file
46
zabbix_scripts/check_sa_learn_sudo
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Spec;
|
||||
open STDERR, '>', File::Spec->devnull() or die "could not open STDERR: $!\n";
|
||||
|
||||
my $what = 'all';
|
||||
GetOptions(
|
||||
"what=s" => \$what
|
||||
);
|
||||
|
||||
my @salearn = qx(sa-learn --dump magic);
|
||||
my $data = {
|
||||
spam => 0,
|
||||
ham => 0,
|
||||
token => 0
|
||||
};
|
||||
|
||||
foreach my $line (@salearn){
|
||||
if ($line =~ m/(\d+)\s*0\s*non-token\sdata:\snspam$/){
|
||||
$data->{spam} = $1;
|
||||
}
|
||||
elsif ($line =~ m/(\d+)\s*0\s*non-token\sdata:\snham$/){
|
||||
$data->{ham} = $1;
|
||||
}
|
||||
elsif ($line =~ m/(\d+)\s*0\s*non-token\sdata:\sntokens$/){
|
||||
$data->{token} = $1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($what eq 'spam'){
|
||||
print $data->{spam} . "\n";
|
||||
}
|
||||
elsif ($what eq 'ham'){
|
||||
print $data->{ham} . "\n";
|
||||
}
|
||||
elsif ($what eq 'token'){
|
||||
print $data->{token} . "\n";
|
||||
}
|
||||
else{
|
||||
print to_json($data);
|
||||
}
|
||||
exit(0);
|
188
zabbix_scripts/check_samba_dc_sudo
Normal file
188
zabbix_scripts/check_samba_dc_sudo
Normal file
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
use Date::Parse;
|
||||
use File::ReadBackwards;
|
||||
use Data::Dumper;
|
||||
|
||||
my $samba_tool = which('samba-tool');
|
||||
my $pdbedit = which('pdbedit');
|
||||
# Number of seconds in the past to count authentications
|
||||
my $since = 300;
|
||||
my $pretty = 0;
|
||||
my $general = 1;
|
||||
my $ou = undef;
|
||||
|
||||
# This log is expected to be in JSON format. For example, in smb.conf :
|
||||
# log level = 1 auth_audit:3 auth_json_audit:4@/var/log/samba/audit_auth.log
|
||||
my $audit_auth_log = '/var/log/samba/json/auth.log';
|
||||
|
||||
if (not defined $samba_tool or not defined $pdbedit){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 1;
|
||||
}
|
||||
|
||||
GetOptions(
|
||||
'pretty' => \$pretty,
|
||||
'since=i' => \$since,
|
||||
'audit-auth-log=s' => \$audit_auth_log,
|
||||
'general' => \$general,
|
||||
'ou=s' => \$ou
|
||||
);
|
||||
|
||||
if ($since !~ m/^\d+$/){
|
||||
die "Invalid value for since\n";
|
||||
}
|
||||
|
||||
my $json = {};
|
||||
|
||||
if (defined $ou){
|
||||
$json = {
|
||||
objects => 0
|
||||
};
|
||||
if ($ou !~ m/^(?<RDN>(?<Key>(?:\\[0-9A-Fa-f]{2}|\\\[^=\,\\]|[^=\,\\]+)+)\=(?<Value>(?:\\[0-9A-Fa-f]{2}|\\\[^=\,\\]|[^=\,\\]+)+))(?:\s*\,\s*(?<RDN>(?<Key>(?:\\[0-9A-Fa-f]{2}|\\\[^=\,\\]|[^=\,\\]+)+)\=(?<Value>(?:\\[0-9A-Fa-f]{2}|\\\[^=\,\\]|[^=\,\\]+)+)))*$/){
|
||||
die "Invalid OU\n";
|
||||
}
|
||||
foreach (qx($samba_tool ou listobjects '$ou' 2>/dev/null)){
|
||||
die "Error while counting objects of OU $ou\n" if ($? != 0);
|
||||
chomp;
|
||||
$json->{objects}++;
|
||||
}
|
||||
} elsif ($general){
|
||||
$json = {
|
||||
accounts => {
|
||||
users => 0,
|
||||
inactive_users => 0,
|
||||
active_users => 0,
|
||||
groups => 0,
|
||||
computers => 0
|
||||
},
|
||||
replication => 'UNKNWON',
|
||||
processes => {
|
||||
cldap_server => 0,
|
||||
kccsrv => 0,
|
||||
dreplsrv => 0,
|
||||
ldap_server => 0,
|
||||
kdc_server => 0,
|
||||
dnsupdate => 0,
|
||||
'notify-daemon' => 0,
|
||||
rpc_server => 0,
|
||||
winbind_server => 0,
|
||||
nbt_server => 0,
|
||||
dnssrv => 0,
|
||||
samba => 0,
|
||||
},
|
||||
gpo => 0,
|
||||
ou => 0,
|
||||
activity => {
|
||||
authentications => {
|
||||
users => {
|
||||
success => 0,
|
||||
failure => 0
|
||||
},
|
||||
computers => {
|
||||
success => 0,
|
||||
failure => 0
|
||||
}
|
||||
},
|
||||
authorizations => {
|
||||
users => 0,
|
||||
computers => 0
|
||||
},
|
||||
since => $since
|
||||
}
|
||||
};
|
||||
|
||||
# Get the numbers of users. pdbedit is prefered here because we can
|
||||
# differentiate active and inactive users, which samba-tool can't do
|
||||
# While at it, also get the computers
|
||||
foreach (qx($pdbedit -L -v)){
|
||||
next unless (m/^Account Flags:\s+\[(.*)\]/);
|
||||
my $flags = $1;
|
||||
if ($flags =~ m/U/){
|
||||
$json->{accounts}->{users}++;
|
||||
if ($flags =~ m/D/){
|
||||
$json->{accounts}->{inactive_users}++;
|
||||
} else {
|
||||
$json->{accounts}->{active_users}++;
|
||||
}
|
||||
} elsif ($flags =~ m/W/){
|
||||
$json->{accounts}->{computers}++;
|
||||
}
|
||||
}
|
||||
|
||||
# Now count groups
|
||||
foreach (qx($samba_tool group list 2>/dev/null)){
|
||||
$json->{accounts}->{groups}++;
|
||||
}
|
||||
|
||||
# Get replication status
|
||||
# We want just a quick summary, so only output the first line
|
||||
# manual checks will be needed to get the details, but if this field doesn't contains [ALL GOOD],
|
||||
# then something is probably wrong
|
||||
$json->{replication} = (split(/\n/, qx($samba_tool drs showrepl --summary 2>/dev/null)))[0];
|
||||
|
||||
# Get the list of workers
|
||||
foreach (qx($samba_tool processes 2>/dev/null)){
|
||||
if (/^([^\(\s]+).+\d+$/){
|
||||
$json->{processes}->{$1}++;
|
||||
}
|
||||
}
|
||||
|
||||
# Get the number of GPO
|
||||
foreach (qx($samba_tool gpo listall 2>/dev/null)){
|
||||
next unless (/^GPO/);
|
||||
$json->{gpo}++;
|
||||
}
|
||||
|
||||
# Get the number of OU
|
||||
foreach (qx($samba_tool ou list 2>/dev/null)){
|
||||
$json->{ou}++;
|
||||
}
|
||||
|
||||
if (-e $audit_auth_log){
|
||||
my $backward = File::ReadBackwards->new( $audit_auth_log ) or die "Couldn't open $audit_auth_log : $!\n";
|
||||
while (defined (my $line = $backward->readline)){
|
||||
my $event;
|
||||
eval {
|
||||
$event = from_json($line);
|
||||
};
|
||||
# Skip the log entry if we can't parse JSON
|
||||
next if (not defined $event);
|
||||
my $type = $event->{type};
|
||||
# We're only interested in Authentication and Authorization messages
|
||||
next if ($type ne 'Authentication' and $type ne 'Authorization');
|
||||
# Parse the date in the timstamp field
|
||||
my $timestamp = str2time($event->{timestamp});
|
||||
|
||||
# Skip if date couldn't be parsed
|
||||
next if (not defined $timestamp);
|
||||
# As we're reading in reverse order, if we reached an events prior to now - since, then we can stop, as all the other will be even earlier
|
||||
last if (time() - $timestamp > $since);
|
||||
|
||||
my $subject;
|
||||
if ($type eq 'Authentication'){
|
||||
if ($event->{Authentication}->{status} eq 'NT_STATUS_PROTOCOL_UNREACHABLE'){
|
||||
# Ignore NT_STATUS_PROTOCOL_UNREACHABLE as they are harmless
|
||||
next;
|
||||
}
|
||||
# Accounts ending with $ are for computers
|
||||
$subject = (($event->{$type}->{mappedAccount} || $event->{$type}->{clientAccount} || '')=~ m/\$(\@.+)?$/) ? 'computers' : 'users';
|
||||
if ($event->{Authentication}->{status} eq 'NT_STATUS_OK'){
|
||||
$json->{activity}->{authentications}->{$subject}->{success}++;
|
||||
} else {
|
||||
$json->{activity}->{authentications}->{$subject}->{failure}++;
|
||||
}
|
||||
} else {
|
||||
$subject = ($event->{$type}->{account} =~ m/\$$/) ? 'computers' : 'users';
|
||||
$json->{activity}->{authorizations}->{$subject}++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
|
@ -1,44 +1,32 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Config::Simple;
|
||||
|
||||
my $what = $ARGV[0];
|
||||
my $thres = $ARGV[1];
|
||||
|
||||
unless (defined $what){
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
open SENSORS, ('</etc/zabbix/sensors.conf') ||
|
||||
die "Couldn't open /etc/zabbix/sensors.conf: $!\n";
|
||||
my $cfg = new Config::Simple;
|
||||
$cfg->read('/etc/zabbix/sensors.ini');
|
||||
|
||||
my $ret = 'ZBX_NOTSUPPORTED';
|
||||
|
||||
foreach (<SENSORS>){
|
||||
next unless (/^$what(\s+)?=(\s+)?(.*)!(\-?\d+)!(\-?\d+)$/);
|
||||
my $cmd = $3;
|
||||
my $high = $4;
|
||||
my $low = $5;
|
||||
if (!defined $thres){
|
||||
$ret = `$cmd`;
|
||||
}
|
||||
elsif ($thres eq 'high'){
|
||||
$ret = $high
|
||||
}
|
||||
elsif ($thres eq 'low'){
|
||||
$ret = $low;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
my $sensor = $cfg->get_block($what);
|
||||
if ($sensor && $sensor->{cmd}){
|
||||
$ret = qx($sensor->{cmd});
|
||||
}
|
||||
|
||||
print $ret;
|
||||
exit(0);
|
||||
|
||||
sub usage {
|
||||
print <<"EOF";
|
||||
|
||||
Usage: $0 sensor_name [high|low]
|
||||
Usage: $0 sensor_name
|
||||
|
||||
EOF
|
||||
}
|
||||
|
|
87
zabbix_scripts/check_squid
Normal file
87
zabbix_scripts/check_squid
Normal file
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use LWP::Simple;
|
||||
use Getopt::Long;
|
||||
use JSON;
|
||||
|
||||
my $uri = 'http://127.0.0.1:3128/squid-internal-mgr/info';
|
||||
my $what = 'all';
|
||||
my $help = 0;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"uri=s" => \$uri,
|
||||
"what=s" => \$what,
|
||||
"help" => \$help,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
my $res = {};
|
||||
my $status = get($uri);
|
||||
|
||||
|
||||
unless ($status){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 1;
|
||||
}
|
||||
|
||||
foreach my $line (split(/\n/, $status)){
|
||||
if ($line =~ m/^Squid Object Cache: Version (\d+(\.\d+)*)/){
|
||||
$res->{version} = $1;
|
||||
} elsif ($line =~ m/^\s+Number of clients accessing cache:\s+(\d+)/){
|
||||
$res->{clients_num} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Number of HTTP requests received:\s+(\d+)/){
|
||||
$res->{requests} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Hits as % of all requests:\s+5min:\s+(\d+(\.\d+)?)%,/){
|
||||
$res->{hits_req_percent} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Hits as % of bytes sent:\s+5min:\s+(\d+(\.\d+)?)%,/){
|
||||
$res->{hits_bytes_percent} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Memory hits as % of hit requests:\s+5min:\s+(\d+(\.\d+)?)%,/){
|
||||
$res->{mem_hits_req_percent} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Disk hits as % of hit requests:\s+5min:\s+(\d+(\.\d+)?)%,/){
|
||||
$res->{disk_hits_req_percent} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Storage Swap size:\s+(\d+)\sKB/){
|
||||
$res->{stor_swap_size} = $1 * 1024;
|
||||
} elsif ($line =~ m/^\s+Storage Swap capacity:\s+(\d+(\.\d+)?)% used, (\d+(\.\d+)?)% free/){
|
||||
($res->{stor_swap_used_percent}, $res->{stor_swap_free_percent}) = ($1 * 1, $3 * 1);
|
||||
} elsif ($line =~ m/^\s+Storage Mem size:\s+(\d+)\sKB/){
|
||||
$res->{stor_mem_size} = $1 * 1024;
|
||||
} elsif ($line =~ m/^\s+Storage Mem capacity:\s+(\d+(\.\d+)?)% used, (\d+(\.\d+)?)% free/){
|
||||
($res->{stor_mem_used_percent}, $res->{stor_mem_free_percent}) = ($1 * 1, $3 * 1);
|
||||
} elsif ($line =~ m/^\s+Mean Object Size:\s+(\d+(\.\d+)?)\sKB/){
|
||||
$res->{mean_object_size} = int($1 * 1024);
|
||||
} elsif ($line =~ m/^\s+CPU Time:\s+(\d+(\.\d+)?)\sseconds/){
|
||||
$res->{cpu_time} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+CPU Usage:\s+(\d+(\.\d+)?)%/){
|
||||
$res->{cpu_usage} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+CPU Usage, 5 minute avg:\s+(\d+(\.\d+)?)%/){
|
||||
$res->{cpu_usage_avg_5min} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Maximum number of file descriptors:\s+(\d+)/){
|
||||
$res->{fd_max} = $1 * 1;
|
||||
} elsif ($line =~ m/^\s+Number of file desc currently in use:\s+(\d+)/){
|
||||
$res->{fd_used} = $1 * 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $res->{fd_max} and defined $res->{fd_used}){
|
||||
$res->{fd_used_percent} = int($res->{fd_used} * 100/ $res->{fd_max});
|
||||
}
|
||||
|
||||
if ($help){
|
||||
print "Valid keys are:\n\n";
|
||||
print "$_\n" for keys %{$res};
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($what eq 'all'){
|
||||
print to_json($res, { pretty => $pretty });
|
||||
}
|
||||
elsif (defined $res->{$what}){
|
||||
print $res->{$what};
|
||||
}
|
||||
else{
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
}
|
||||
exit 0;
|
120
zabbix_scripts/check_stor_dev_sudo
Normal file
120
zabbix_scripts/check_stor_dev_sudo
Normal file
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
|
||||
my $dev = undef;
|
||||
my $type = 'auto';
|
||||
my $what = 'json';
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'device=s' => \$dev,
|
||||
'type=s' => \$type,
|
||||
'what=s' => \$what,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
if (not defined $dev or $dev !~ m|^/dev/\w+(/\w+)*$|){
|
||||
print "Invalid --device\n";
|
||||
exit 1;
|
||||
} elsif ($what !~ m/^\w+$/){
|
||||
print "Invalid --what\n";
|
||||
exit 1;
|
||||
} elsif ($type !~ m/^\w+\+*\w+(,\w+)*$/){
|
||||
print "Invalid --type\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $json = {
|
||||
temperature_celsius => 25,
|
||||
power_on_hours => 0,
|
||||
power_cycle_count => 0,
|
||||
reallocated_sector_count => 0,
|
||||
current_pending_sector => 0,
|
||||
offline_uncorrectable => 0,
|
||||
percent_lifetime_remain => 100,
|
||||
firmware_version => 0
|
||||
};
|
||||
my $smartctl = which('smartctl');
|
||||
|
||||
sub print_out {
|
||||
if ($what eq 'json'){
|
||||
print to_json($json, { pretty => $pretty });
|
||||
exit 0;
|
||||
} elsif (defined $json->{$what}){
|
||||
print $json->{$what} . "\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "ZBX_NOTSUPPORTED\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_smart_attr {
|
||||
my $smart = shift;
|
||||
my $attr = shift;
|
||||
|
||||
if (defined $smart->{ata_smart_attributes}->{table}){
|
||||
foreach (@{$smart->{ata_smart_attributes}->{table}}){
|
||||
if ($_->{name} eq $attr){
|
||||
return $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
if (not defined $smartctl){
|
||||
$what = 'error';
|
||||
print_out();
|
||||
}
|
||||
|
||||
my $data = from_json(qx($smartctl -a $dev -d $type --json=c));
|
||||
|
||||
if (defined $data->{temperature}->{current}){
|
||||
$json->{temperature_celsius} = $data->{temperature}->{current};
|
||||
}
|
||||
|
||||
if (defined $data->{power_on_time}->{hours}){
|
||||
$json->{power_on_hours} = $data->{power_on_time}->{hours};
|
||||
}
|
||||
|
||||
if (defined $data->{power_cycle_count}){
|
||||
$json->{power_cycle_count} = $data->{power_cycle_count};
|
||||
}
|
||||
|
||||
if (defined $data->{firmware_version}){
|
||||
$json->{firmware_version} = $data->{firmware_version};
|
||||
}
|
||||
|
||||
my ($pending, $realloc, $offline, $remain);
|
||||
if ($pending = get_smart_attr($data, 'Current_Pending_Sector')){
|
||||
$json->{current_pending_sector} = $pending->{raw}->{value};
|
||||
}
|
||||
|
||||
if ($realloc = get_smart_attr($data, 'Reallocated_Sector_Ct') || get_smart_attr($data, 'Reallocated_Event_Count')){
|
||||
$json->{reallocated_sector_count} = $realloc->{raw}->{value};
|
||||
} elsif (defined $data->{nvme_smart_health_information_log}->{media_errors}){
|
||||
# NMVe can report media error, so report it as reallocated sectors
|
||||
$json->{reallocated_sector_count} = $data->{nvme_smart_health_information_log}->{media_errors};
|
||||
}
|
||||
|
||||
if ($offline = get_smart_attr($data, 'Offline_Uncorrectable')){
|
||||
$json->{offline_uncorrectable} = $offline->{raw}->{value};
|
||||
}
|
||||
|
||||
if ($remain = get_smart_attr($data, 'Percent_Lifetime_Remain')){
|
||||
$json->{percent_lifetime_remain} = $remain->{value};
|
||||
} elsif ($remain = get_smart_attr($data, 'SSD_Life_Left')){
|
||||
$json->{percent_lifetime_remain} = $remain->{raw}->{value};
|
||||
} elsif ($remain = get_smart_attr($data, 'Wear_Leveling_Count')){
|
||||
$json->{percent_lifetime_remain} = $remain->{value};
|
||||
} elsif (defined $data->{nvme_smart_health_information_log}->{percentage_used}){
|
||||
# NMVe sometime report the estimated life used, instead of the remaining
|
||||
$json->{percent_lifetime_remain} = 100 - $data->{nvme_smart_health_information_log}->{percentage_used};
|
||||
}
|
||||
print_out();
|
262
zabbix_scripts/check_unifi
Executable file
262
zabbix_scripts/check_unifi
Executable file
|
@ -0,0 +1,262 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Cookies;
|
||||
use URI;
|
||||
use Data::Dumper;
|
||||
|
||||
umask 077;
|
||||
|
||||
my $user = 'zabbix';
|
||||
my $pass = 'secret';
|
||||
my $site = 'default';
|
||||
my $url = 'https://localhost:8443';
|
||||
my $certcheck = 1;
|
||||
my $unifi;
|
||||
my $dev;
|
||||
my $station;
|
||||
my $net;
|
||||
my $wlan;
|
||||
my $pretty = 0;
|
||||
|
||||
my $json = {};
|
||||
my $site_id;
|
||||
|
||||
GetOptions (
|
||||
'user=s' => \$user,
|
||||
'password|p=s' => \$pass,
|
||||
'site=s' => \$site,
|
||||
'url=s' => \$url,
|
||||
'cert-check!' => \$certcheck,
|
||||
'unifi' => \$unifi,
|
||||
'dev=s' => \$dev,
|
||||
'station=s' => \$station,
|
||||
'net=s' => \$net,
|
||||
'wlan=s' => \$wlan,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
# If connecting to localhost, no need to check certificate
|
||||
my $uri = URI->new($url);
|
||||
if ($uri->host =~ m/^localhost|127\.0\.0/){
|
||||
$certcheck = 0;
|
||||
}
|
||||
|
||||
my @radio_proto = qw/a b g na ng ac/;
|
||||
my $resp;
|
||||
my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<);
|
||||
my $cj = HTTP::Cookies->new(
|
||||
file => "/tmp/.unifi_$username.txt",
|
||||
autosave => 1,
|
||||
ignore_discard => 1
|
||||
);
|
||||
|
||||
my $sslopts = {};
|
||||
if (not $certcheck){
|
||||
$sslopts = { verify_hostname => 0, SSL_verify_mode => 0 }
|
||||
}
|
||||
my $ua = LWP::UserAgent->new(
|
||||
ssl_opts => $sslopts,
|
||||
cookie_jar => $cj
|
||||
);
|
||||
|
||||
# Check if we need to login
|
||||
$resp = $ua->get($url . '/api/self/sites');
|
||||
if ($resp->is_error){
|
||||
# Log into the API
|
||||
$resp = $ua->post(
|
||||
$url . '/api/login',
|
||||
Content => to_json({ username => $user, password => $pass }),
|
||||
Content_Type => 'application/json;charset=UTF-8'
|
||||
);
|
||||
die "Login failed: " . $resp->message . "\n" if $resp->is_error;
|
||||
$resp = $ua->get($url . '/api/self/sites');
|
||||
die $resp->message . "\n" if $resp->is_error;
|
||||
}
|
||||
|
||||
# Now, we need to get the site ID
|
||||
foreach (@{from_json($resp->decoded_content)->{data}}){
|
||||
if ($_->{name} eq $site || $_->{desc} eq $site){
|
||||
$site_id = $_->{_id};
|
||||
# If site is referenced by description, translate it to name
|
||||
$site = $_->{name} if ($_->{name} ne $site);
|
||||
last;
|
||||
}
|
||||
}
|
||||
die "Site $site not found\n" unless ($site_id);
|
||||
|
||||
# Global info about the instance of Unifi
|
||||
if ($unifi){
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/health');
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
if ($entry->{subsystem} eq 'wlan'){
|
||||
$json->{wireless_clients} = $entry->{num_user};
|
||||
$json->{wireless_guests} = $entry->{num_guest};
|
||||
} elsif ($entry->{subsystem} eq 'lan'){
|
||||
$json->{wired_clients} = $entry->{num_user};
|
||||
$json->{wired_guests} = $entry->{num_guest};
|
||||
}
|
||||
foreach (qw/adopted pending disabled/){
|
||||
$json->{'dev_' . $_} += $entry->{'num_' . $_} if (defined $entry->{'num_' . $_});
|
||||
}
|
||||
foreach (qw/num_ap num_sw num_gw/){
|
||||
$json->{$_} += $entry->{$_} if ($entry->{$_});
|
||||
}
|
||||
}
|
||||
$json->{$_} ||= 0 foreach (qw/wireless_clients wireless_guests
|
||||
wired_clients wired_guests dev_adopted
|
||||
dev_pending dev_disabled num_ap num_sw
|
||||
num_gw/);
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/sysinfo');
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
$json->{$_} = from_json($resp->decoded_content)->{data}->[0]->{$_}
|
||||
foreach (qw/version build update_available/);
|
||||
|
||||
# Get unarchived alarms
|
||||
$resp = $ua->post($url . '/api/s/' . $site . '/stat/alarm',
|
||||
Content => to_json({ archived => 'false' }),
|
||||
Content_Type => 'application/json;charset=UTF-8'
|
||||
);
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
$json->{alarm} = scalar @{from_json($resp->decoded_content)->{data}};
|
||||
|
||||
} elsif ($dev) {
|
||||
# Dev is identified by MAC
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/device/' . $dev);
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
my $obj = from_json($resp->decoded_content)->{data}->[0];
|
||||
foreach (qw/sys_stats locating serial name num_sta user-num_sta
|
||||
guest-num_sta inform_url version model state type
|
||||
cfgversion adopted avg_client_signal/){
|
||||
$json->{$_} = $obj->{$_} if (defined $obj->{$_});
|
||||
}
|
||||
# Convert last seen into a relative time
|
||||
$json->{last_seen} = (defined $obj->{last_seen}) ? time - $obj->{last_seen} : time;
|
||||
# Add some more info in sys_stats
|
||||
$json->{sys_stats}->{$_} = $obj->{'system-stats'}->{$_} foreach (qw/cpu mem uptime/);
|
||||
|
||||
# If this is an ap
|
||||
if ($obj->{type} eq 'uap'){
|
||||
|
||||
foreach (qw/guest-rx_packets guest-tx_packets guest-rx_bytes
|
||||
guest-tx_bytes user-rx_packets user-tx_packets
|
||||
user-rx_bytes user-tx_bytes rx_packets tx_packets
|
||||
rx_bytes tx_bytes rx_errors tx_errors
|
||||
rx_dropped tx_dropped/){
|
||||
$json->{net_stats}->{$_} = $obj->{stat}->{ap}->{$_} if (defined $obj->{stat}->{ap}->{$_});
|
||||
}
|
||||
|
||||
# Count the number of SSID served
|
||||
$json->{num_wlan} = scalar @{$obj->{radio_table}};
|
||||
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/sta');
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
|
||||
foreach my $proto (@radio_proto){
|
||||
$json->{$_ . $proto} = 0 foreach (qw/num_sta_ avg_rx_rate_ avg_tx_rate_/);
|
||||
}
|
||||
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
next if (not $entry->{ap_mac} or $entry->{ap_mac} ne $dev or $entry->{is_wired} == JSON::true);
|
||||
foreach (@radio_proto){
|
||||
if ($entry->{radio_proto} eq $_){
|
||||
$json->{'num_sta_' . $_}++;
|
||||
$json->{'avg_rx_rate_' . $_} += $entry->{rx_rate};
|
||||
$json->{'avg_tx_rate_' . $_} += $entry->{tx_rate};
|
||||
}
|
||||
}
|
||||
$json->{$_} += $entry->{$_} foreach (qw/rx_bytes tx_bytes rx_packets tx_packets/);
|
||||
$json->{'avg_' . $_} += $entry->{$_} foreach (qw/satisfaction tx_power signal noise/);
|
||||
}
|
||||
|
||||
# Now lets compute average values
|
||||
$json->{'avg_' . $_} = ($json->{num_sta} == 0) ? undef : $json->{'avg_' . $_} / $json->{num_sta}
|
||||
foreach (qw/satisfaction tx_power signal noise/);
|
||||
foreach my $proto (@radio_proto){
|
||||
$json->{'avg_' . $_ . '_rate_' . $proto} = ($json->{'num_sta_' . $proto} == 0) ?
|
||||
undef : $json->{'avg_' . $_ . '_rate_' . $proto} / $json->{'num_sta_' . $proto}
|
||||
foreach (qw/tx rx/);
|
||||
}
|
||||
} elsif ($obj->{type} eq 'usw'){
|
||||
foreach (qw/rx_packets tx_packets
|
||||
rx_bytes tx_bytes rx_errors tx_errors
|
||||
rx_dropped tx_dropped/){
|
||||
$json->{net_stats}->{$_} = $obj->{stat}->{sw}->{$_} if (defined $obj->{stat}->{sw}->{$_});
|
||||
}
|
||||
}
|
||||
} elsif ($station) {
|
||||
# Client is identified by MAC
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/sta/' . $station);
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
my $obj = from_json($resp->decoded_content)->{data}->[0];
|
||||
my @client_base = qw/rx_packets tx_packets rx_bytes tx_bytes hostname last_seen ip authorized oui is_guest/;
|
||||
foreach (@client_base){
|
||||
$json->{$_} = $obj->{$_} || 0;
|
||||
}
|
||||
# Convert last_seen to relative
|
||||
$json->{last_seen} = (defined $obj->{last_seen}) ? time - $obj->{last_seen} : time;
|
||||
|
||||
# For wireless stations, we gather some more info
|
||||
if ($obj->{is_wired} == JSON::false){
|
||||
my @client_wireless = qw/rx_rate tx_rate essid ap_mac tx_power radio_proto signal noise satisfaction/;
|
||||
foreach (@client_wireless){
|
||||
$json->{$_} = $obj->{$_} || 0;
|
||||
}
|
||||
# We have the MAC of the AP, lets try to find the name of this AP
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/device/' . $json->{ap_mac});
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
$json->{ap} = from_json($resp->decoded_content)->{data}->[0]->{name};
|
||||
}
|
||||
|
||||
} elsif ($wlan) {
|
||||
# Wlan is identified by ID
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/rest/wlanconf/' . $wlan);
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
my $obj = from_json($resp->decoded_content)->{data}->[0];
|
||||
foreach (qw/name security mac_filter_policy vlan/){
|
||||
$json->{$_} = $obj->{$_};
|
||||
}
|
||||
# For boolean, we need to convert
|
||||
foreach (qw/enabled is_guest mac_filter_enabled vlan_enabled/){
|
||||
$json->{$_} = (defined $obj->{$_} and $obj->{$_} == JSON::PP::true) ? 1 : 0;
|
||||
}
|
||||
|
||||
# Now, we need to count stations for each SSID
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/sta');
|
||||
die "ZBX_NOTSUPPORTED\n" if $resp->is_error;
|
||||
|
||||
# Set default values to 0
|
||||
$json->{num_sta} = 0;
|
||||
$json->{'num_sta_' . $_} = 0 foreach (@radio_proto);
|
||||
$json->{$_} = 0 foreach (qw/rx_bytes tx_bytes rx_packets tx_packets/);
|
||||
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
next if (not $entry->{essid} or $entry->{essid} ne $json->{name} or $entry->{is_wired} == JSON::PP::true);
|
||||
$json->{num_sta}++;
|
||||
foreach (@radio_proto){
|
||||
if ($entry->{radio_proto} eq $_){
|
||||
$json->{'num_sta_' . $_}++;
|
||||
$json->{'avg_rx_rate_' . $_} += $entry->{rx_rate};
|
||||
$json->{'avg_tx_rate_' . $_} += $entry->{tx_rate};
|
||||
}
|
||||
}
|
||||
$json->{$_} += $entry->{$_} foreach (qw/rx_bytes tx_bytes rx_packets tx_packets/);
|
||||
$json->{'avg_' . $_} += $entry->{$_} foreach (qw/satisfaction tx_power signal noise/);
|
||||
}
|
||||
|
||||
# Now lets compute average values
|
||||
$json->{'avg_' . $_} = ($json->{num_sta} == 0) ? undef : $json->{'avg_' . $_} / $json->{num_sta}
|
||||
foreach (qw/satisfaction tx_power signal noise/);
|
||||
foreach my $proto (@radio_proto){
|
||||
$json->{'avg_' . $_ . '_rate_' . $proto} = ($json->{'num_sta_' . $proto} == 0) ?
|
||||
undef : $json->{'avg_' . $_ . '_rate_' . $proto} / $json->{'num_sta_' . $proto}
|
||||
foreach (qw/tx rx/);
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
45
zabbix_scripts/check_vdo_sudo
Normal file
45
zabbix_scripts/check_vdo_sudo
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
|
||||
my $vdostats = which('vdostats');
|
||||
my $json = {};
|
||||
my $pretty = 0;
|
||||
my $volume = undef;
|
||||
my $val = undef;
|
||||
|
||||
GetOptions(
|
||||
'volume=s' => \$volume,
|
||||
'value=s' => \$val,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
if ($volume) {
|
||||
if ($volume !~ m/^\w+$/){
|
||||
die "Invalide volume name\n";
|
||||
}
|
||||
foreach my $line (qx($vdostats --all $volume)){
|
||||
if ($line =~ m/^\s+([^:]+)\s+:\s+([\d\w]+)/){
|
||||
my ($key,$val) = ($1,$2);
|
||||
# Cleanup key
|
||||
$key =~ s/\s+$//;
|
||||
$key =~ s/\s+/_/g;
|
||||
$key =~ s/\(|\)//g;
|
||||
$key =~ s/%/pct/g;
|
||||
$json->{lc $key} = $val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 0;
|
||||
}
|
||||
if (defined $val) {
|
||||
print $json->{$val} || 'ZBX_NOTSUPPORTED';
|
||||
} else {
|
||||
print to_json($json, { pretty => $pretty });
|
||||
}
|
||||
print "\n";
|
182
zabbix_scripts/check_zfs
Normal file
182
zabbix_scripts/check_zfs
Normal file
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
|
||||
my $json = {};
|
||||
my $pool = undef;
|
||||
my $dataset = undef;
|
||||
my $sanoidmon = undef;
|
||||
my $stats = undef;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"zpool|pool=s" => \$pool,
|
||||
"dataset=s" => \$dataset,
|
||||
"sanoid=s" => \$sanoidmon,
|
||||
"stats=s" => \$stats,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
my $zpool = which('zpool');
|
||||
my $zfs = which('zfs');
|
||||
my $sanoid = which('sanoid');
|
||||
|
||||
if (not $zpool or not $zfs){
|
||||
print 'ZBX_NOTSUPPOTED';
|
||||
exit 0;
|
||||
}
|
||||
if (defined $sanoidmon and not $sanoid){
|
||||
die 'ZBX_NOTSUPPOTED';
|
||||
}
|
||||
if (defined $sanoidmon and not grep { $_ eq $sanoidmon } qw(snapshot capacity health)){
|
||||
die 'ZBX_NOTSUPPOTED';
|
||||
}
|
||||
|
||||
if (not $pool and not $dataset and not $sanoidmon and not $stats){
|
||||
print <<_EOF;
|
||||
Usage:
|
||||
$0 [--zpool=<name>|--dataset=<fs zvol or snap>|--sanoid=<snapshot|capacity|health>]
|
||||
_EOF
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Value map. For Zabbix, we want 0 instead of none
|
||||
# We also prefer on/off represented as 1/0 as it's more efficient
|
||||
my $map = {
|
||||
18446744073709551615 => 0, # See https://github.com/zfsonlinux/zfs/issues/9306
|
||||
none => 0,
|
||||
on => 1,
|
||||
off => 0
|
||||
};
|
||||
|
||||
if ($pool){
|
||||
foreach (qx($zpool get all $pool -p -H)){
|
||||
chomp;
|
||||
my @parse = split /\t+/, $_;
|
||||
$json->{$parse[1]} = (defined $map->{$parse[2]}) ? $map->{$parse[2]} : $parse[2];
|
||||
$json->{errors} = get_zpool_errors($pool);
|
||||
$json->{stats} = get_zpool_stats($pool);
|
||||
}
|
||||
} elsif ($dataset){
|
||||
# Convert %40 back to @ (we send them as %40 in the discovery because @ is not allowed in item keys
|
||||
$dataset =~ s/%40/\@/g;
|
||||
foreach (qx($zfs get all $dataset -p -H)){
|
||||
chomp;
|
||||
my @parse = split /\t+/, $_;
|
||||
$json->{$parse[1]} = (defined $map->{$parse[2]}) ? $map->{$parse[2]} : $parse[2];
|
||||
if ($parse[1] =~ m/compressratio$/){
|
||||
# Remove trailing x for compressratio and refcompressratio as before 0.8.0 it can be like 1.23x
|
||||
$json->{$parse[1]} =~ s/x$//;
|
||||
}
|
||||
}
|
||||
} elsif ($sanoidmon){
|
||||
print qx($sanoid --monitor-$sanoidmon);
|
||||
exit $?;
|
||||
} elsif ($stats){
|
||||
if (not -e '/proc/spl/kstat/zfs/' . $stats){
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
exit 0;
|
||||
}
|
||||
open STATS, '</proc/spl/kstat/zfs/' . $stats;
|
||||
while (<STATS>){
|
||||
next unless (m/^(\w+)\s+4\s+(\d+)$/);
|
||||
$json->{$1} = $2;
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
||||
exit 0;
|
||||
|
||||
sub get_zpool_errors {
|
||||
my $pool = shift;
|
||||
my $errors = {
|
||||
read_errors => 0,
|
||||
write_errors => 0,
|
||||
cksum_errors => 0
|
||||
};
|
||||
my $i = 0;
|
||||
my $index = {};
|
||||
foreach my $line (qx($zpool status $pool 2>/dev/null)){
|
||||
# Output looks like
|
||||
# pool: rpool
|
||||
# state: ONLINE
|
||||
# status: One or more devices has experienced an unrecoverable error. An
|
||||
# attempt was made to correct the error. Applications are unaffected.
|
||||
# action: Determine if the device needs to be replaced, and clear the errors
|
||||
# using 'zpool clear' or replace the device with 'zpool replace'.
|
||||
# see: http://zfsonlinux.org/msg/ZFS-8000-9P
|
||||
# scan: scrub repaired 0B in 0h5m with 0 errors on Tue May 29 10:04:31 2018
|
||||
# config:
|
||||
#
|
||||
# NAME STATE READ WRITE CKSUM
|
||||
# rpool ONLINE 0 0 0
|
||||
# mirror-0 ONLINE 0 0 0
|
||||
# sda2 ONLINE 0 0 0
|
||||
# sdb2 ONLINE 0 0 474
|
||||
#
|
||||
# errors: No known data errors
|
||||
|
||||
# We want to save status, action, scan and errors
|
||||
if ($line =~ m/^\s*(scan|action|status|errors):\s+(\w+.*)/){
|
||||
$errors->{$1} = $2;
|
||||
$index->{$i} = $1;
|
||||
} elsif ($line !~ /:/ and defined $index->{$i-1}){
|
||||
# Here, we reconstitute multiline values (like status and action)
|
||||
chomp($line);
|
||||
$line =~ s/\s+/ /g;
|
||||
$errors->{$index->{$i-1}} .= $line;
|
||||
} elsif ($line =~ m/\s+[a-zA-Z0-9_\-]+\s+[A-Z]+\s+(?<read>\d+(\.\d+)?)(?<read_suffix>[KMT])?\s+(?<write>\d+(\.\d+)?)(?<write_suffix>[KMT])?\s+(?<cksum>\d+(\.\d+)?)(?<cksum_suffix>[KMT])?/){
|
||||
# And here, we count the number of read, write and checksum errors
|
||||
# Note that on ZoL 0.8.0 we could use zpool status -p to get rid of the suffixes
|
||||
# But -p is not supported on 0.7 and earlier, so, we just convert them manually
|
||||
$errors->{read_errors} += convert_suffix($+{'read'},$+{'read_suffix'});
|
||||
$errors->{write_errors} += convert_suffix($+{'write'},$+{'write_suffix'});
|
||||
$errors->{cksum_errors} += convert_suffix($+{'write'},$+{'write_suffix'});
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
# Ensure evey item returns something
|
||||
$errors->{$_} ||= '' foreach (qw(scan action status errors));
|
||||
return $errors;
|
||||
}
|
||||
|
||||
# Error counter can be suffixed. Apply this suffix to get raw error numbers
|
||||
sub convert_suffix {
|
||||
my $val = shift;
|
||||
my $suf = shift;
|
||||
if (!$suf){
|
||||
return $val;
|
||||
} elsif ($suf eq 'K'){
|
||||
$val *= 1000;
|
||||
} elsif ($suf eq 'M') {
|
||||
$val *= 1000000;
|
||||
} elsif ($suf eq 'T') {
|
||||
$val *= 1000000000;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
sub get_zpool_stats {
|
||||
my $pool = shift;
|
||||
my $stats = {};
|
||||
open UPTIME, "</proc/uptime";
|
||||
$_ = <UPTIME>;
|
||||
chomp;
|
||||
my ($uptime , undef) = split;
|
||||
$uptime = int $uptime;
|
||||
close UPTIME;
|
||||
foreach my $line (qx($zpool iostat $pool -pH)){
|
||||
if ($line =~ m/^$pool\s+\d+\s+\d+\s+(?<reads>\d+)\s+(?<writes>\d+)\s+(?<nread>\d+)\s+(?<nwritten>\d+)/){
|
||||
# zpool iostat shows average IO since boot, so just multiply it
|
||||
# by the uptime in seconds to get cumulated IO since boot
|
||||
# Zabbix server will then be able to calculate the delta between two values
|
||||
$stats->{$_} = $+{$_} * $uptime foreach (keys %+);
|
||||
last;
|
||||
}
|
||||
}
|
||||
return $stats;
|
||||
}
|
59
zabbix_scripts/check_zimbra_sudo
Normal file
59
zabbix_scripts/check_zimbra_sudo
Normal file
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use JSON;
|
||||
use POSIX;
|
||||
use Getopt::Long;
|
||||
use Net::Domain qw(hostfqdn);
|
||||
use Data::Dumper;
|
||||
|
||||
my $pretty = 0;
|
||||
my $status = 'all';
|
||||
|
||||
GetOptions(
|
||||
"pretty" => \$pretty,
|
||||
"status=s" => \$status
|
||||
);
|
||||
|
||||
if (defined $service and $service !~ m/^\w+$/){
|
||||
die "Invelid service name\n";
|
||||
}
|
||||
|
||||
my $zmprov = '/opt/zimbra/bin/zmprov';
|
||||
my $zmcontrol = '/opt/zimbra/bin/zmcontrol';
|
||||
my $hostname = hostfqdn();
|
||||
|
||||
# We need to switch to zimbra
|
||||
my $uid = getuid();
|
||||
my $gid = getgid();
|
||||
my (undef,undef,$zimuid,$zimgid) = getpwnam('zimbra');
|
||||
|
||||
if (not defined $zimuid or not defined $zimgid or not -e $zmprov){
|
||||
print 'ZBX_NOTSUPPOTED';
|
||||
exit;
|
||||
}
|
||||
|
||||
setuid($zimuid) if ($uid ne $zimuid);
|
||||
setgid($zimgid) if ($gid ne $zimgid);
|
||||
|
||||
# If there's no zimbra user or no zmcontrol, return unsupported item
|
||||
if (not defined $zimuid or not defined $zimgid or not -e $zmprov){
|
||||
print 'ZBX_NOTSUPPOTED';
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $output = {};
|
||||
|
||||
if (defined $status){
|
||||
foreach my $line (qx($zmcontrol status)){
|
||||
if ($line =~ m/^\s+(\w+)(\swebapp)?\s+(Running|Stopped)/){
|
||||
$output->{$1} = ($3 eq 'Running') ? 1 : 0;
|
||||
}
|
||||
}
|
||||
if ($status eq 'all'){
|
||||
print to_json($output, { pretty => $pretty });
|
||||
} elsif (defined $output->{$status}){
|
||||
print $output->{$status}
|
||||
} else {
|
||||
print 'ZBX_NOTSUPPORTED';
|
||||
}
|
||||
}
|
|
@ -1,24 +1,24 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use lib "/usr/share/BackupPC/lib";
|
||||
use lib "/usr/share/backuppc/lib";
|
||||
use lib "/usr/local/BackupPC/lib";
|
||||
use BackupPC::Lib;
|
||||
use BackupPC::CGI::Lib;
|
||||
use POSIX;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use MIME::Base64 qw( decode_base64 );
|
||||
|
||||
my $regex = '.*';
|
||||
my $base64 = 0;
|
||||
my $hosts = 1;
|
||||
my $entities = 0;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"regex=s" => \$regex,
|
||||
"base64" => \$base64
|
||||
"hosts" => \$hosts,
|
||||
"entities" => \$entities,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
$regex = decode_base64($regex) if ($base64);
|
||||
$regex = qr($regex);
|
||||
|
||||
# We need to switch to backuppc UID/GID
|
||||
my $uid = getuid();
|
||||
my $gid = getgid();
|
||||
|
@ -32,20 +32,35 @@ my $mainConf = $bpc->ConfigDataRead();
|
|||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
foreach my $host (keys %$hosts){
|
||||
next unless ($host =~ m!$regex!);
|
||||
|
||||
if ($entities) {
|
||||
my %entities = ();
|
||||
foreach my $host ( keys %$hosts ){
|
||||
if ( $host =~ m/^(?:vm_)?([^_]+)_.*/ and $1 ne 'vm' ) {
|
||||
$entities{$1}= 1;
|
||||
}
|
||||
}
|
||||
push @{$json->{data}}, { '{#BPC_ENTITY}' => $_ } foreach ( keys %entities );
|
||||
} elsif ($hosts){
|
||||
foreach my $host ( keys %$hosts ){
|
||||
my $hostConf = $bpc->ConfigDataRead($host);
|
||||
my $conf = { %$mainConf, %$hostConf };
|
||||
my $warning = $conf->{EMailNotifyOldBackupDays};
|
||||
my $errors = (defined $conf->{MaxXferError}) ? $conf->{MaxXferError}: '0';
|
||||
my $status = ($conf->{BackupsDisable} eq '1') ? 'disabled':(($conf->{ZabbixMonitoring} eq '0') ? 'disabled':'enabled');
|
||||
my $errors = ( defined $conf->{MaxXferError} ) ? $conf->{MaxXferError} : '0';
|
||||
my $monitoring = $conf->{ZabbixMonitoring} || 1;
|
||||
my $sizeTooBigFactor = $conf->{ZabbixSizeTooBigFactor} || 6;
|
||||
my $sizeTooSmallFactor = $conf->{ZabbixSizeTooSmallFactor} || 3;
|
||||
my $status = ( $conf->{BackupsDisable} gt 0 or $monitoring eq '0' ) ? '0' : '1';
|
||||
push @{$json->{data}},
|
||||
{
|
||||
"{#BPCHOST}" => $host,
|
||||
"{#BPCNOBACKUPWARNING}" => $warning,
|
||||
"{#BPCMAXERROR}" => $errors,
|
||||
"{#BPCSTATUS}" => $status,
|
||||
"{#BPC_TOO_BIG_FACTOR}" => $sizeTooBigFactor,
|
||||
"{#BPC_TOO_SMALL_FACTOR}" => $sizeTooSmallFactor,
|
||||
};
|
||||
}
|
||||
}
|
||||
print to_json($json);
|
||||
print to_json( $json, { pretty => $pretty } );
|
||||
exit(0);
|
||||
|
|
|
@ -1,22 +1,39 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use Zabbix::Agent::Addons::Disks;
|
||||
use JSON;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
|
||||
my $pretty = 0;
|
||||
GetOptions(
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $lsblk = which('lsblk');
|
||||
|
||||
opendir(my $dh, "/sys/block") or die "Couldn't open /sys/block: $!";
|
||||
my @blocks = grep { $_ !~ m/^\./ } readdir($dh);
|
||||
closedir($dh);
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
foreach my $block (@blocks){
|
||||
my $size = 1;
|
||||
if ( -e "/sys/block/$block/size"){
|
||||
open SIZE, "/sys/block/$block/size";
|
||||
$size = join "", <SIZE>;
|
||||
close SIZE;
|
||||
chomp($size);
|
||||
next if ($size eq '0');
|
||||
if (defined $lsblk){
|
||||
foreach my $line (qx($lsblk -o KNAME,TYPE,SIZE -r -n -b)){
|
||||
my ($block,$type,$size) = split(/\s+/, $line);
|
||||
push @{$json->{data}}, {
|
||||
"{#BLOCKDEVICE}" => $block, # Compat with previous zabbix-agent-addons
|
||||
"{#DEVNAME}" => $block, # New macro name for the native vfs.dev.discovery key in 4.4
|
||||
"{#DEVTYPE}" => $type,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
# Fallback if lsblk is not available
|
||||
foreach my $block (Zabbix::Agent::Addons::Disks::list_block_dev()){
|
||||
push @{$json->{data}}, {
|
||||
"{#BLOCKDEVICE}" => $block,
|
||||
"{#DEVNAME}" => $block,
|
||||
"{#DEVTYPE}" => 'disk'
|
||||
};
|
||||
}
|
||||
push @{$json->{data}}, { "{#BLOCKDEVICE}" => $block, "{#BLOCKSIZE}" => $size };
|
||||
}
|
||||
print to_json($json);
|
||||
print to_json($json, { pretty => $pretty });
|
||||
exit(0);
|
||||
|
|
68
zabbix_scripts/disco_docker_sudo
Executable file
68
zabbix_scripts/disco_docker_sudo
Executable file
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
use Data::Dumper;
|
||||
|
||||
my $what = 'containers';
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'what=s' => \$what,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $json = [];
|
||||
|
||||
my $docker = which('docker');
|
||||
|
||||
# If the docker cli is not available, terminate now
|
||||
if (not defined $docker){
|
||||
print $json . "\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my $format;
|
||||
my $cmd;
|
||||
if ($what =~ m/^containers?/){
|
||||
$format = '{' .
|
||||
'"{#DOCKER_CONTAINER_ID}":"{{ .ID }}",' .
|
||||
'"{#DOCKER_CONTAINER_IMAGE}": "{{ .Image }}",' .
|
||||
'"{#DOCKER_CONTAINER_NAME}":"{{ .Names }}",' .
|
||||
'"{#DOCKER_CONTAINER_STATUS}":"{{ .Status }}"' .
|
||||
'}';
|
||||
$cmd = "$docker container list --all --format '$format'";
|
||||
} elsif ($what =~ m/^networks?/){
|
||||
$format = '{' .
|
||||
'"{#DOCKER_NET_ID}":"{{ .ID }}",' .
|
||||
'"{#DOCKER_NET_NAME}":"{{ .Name }}",' .
|
||||
'"{#DOCKER_NET_DRIVER}":"{{ .Driver }}",' .
|
||||
'"{#DOCKER_NET_SCOPE}":"{{ .Scope }}"' .
|
||||
'}';
|
||||
$cmd = "$docker network list --format '$format'";
|
||||
} elsif ($what =~ m/^volumes?/){
|
||||
$format = '{' .
|
||||
'"{#DOCKER_VOL_NAME}":"{{ .Name }}",' .
|
||||
'"{#DOCKER_VOL_DRIVER}":"{{ .Driver }}",' .
|
||||
'"{#DOCKER_VOL_SCOPE}":"{{ .Scope }}"' .
|
||||
'}';
|
||||
$cmd = "$docker volume list --format '$format'";
|
||||
} else {
|
||||
print <<_EOF
|
||||
Usage: $0 --what=<item to discover> [--pretty]
|
||||
with available item being
|
||||
* containers : list containers, including stopped ones
|
||||
* networks : list networks
|
||||
* volumes : list volumes
|
||||
_EOF
|
||||
}
|
||||
|
||||
foreach my $line (qx($cmd)){
|
||||
chomp $line;
|
||||
push @{$json}, from_json($line);
|
||||
}
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
||||
exit(0);
|
26
zabbix_scripts/disco_drbd
Normal file
26
zabbix_scripts/disco_drbd
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use File::Which;
|
||||
use JSON;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
my $drbdoverview = which('drbd-overview');
|
||||
|
||||
if ($drbdoverview){
|
||||
open RES, "$drbdoverview |" || die "Couldn't execute $drbdoverview";
|
||||
foreach my $l (<RES>){
|
||||
if ($l =~ m{(\d+):(\w+)/\d+}){
|
||||
push @{$json->{data}}, {
|
||||
"{#DRBD_RES_ID}" => $1,
|
||||
"{#DRBD_RES_NAME}" => $2
|
||||
};
|
||||
}
|
||||
}
|
||||
close RES;
|
||||
}
|
||||
|
||||
print to_json($json);
|
||||
exit(0);
|
95
zabbix_scripts/disco_elasticsearch
Normal file
95
zabbix_scripts/disco_elasticsearch
Normal file
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Request::Common;
|
||||
use URI;
|
||||
use Data::Dumper;
|
||||
|
||||
my $user = undef;
|
||||
my $pass = undef;
|
||||
my $url = 'http://localhost:9200';
|
||||
my $certcheck = 1;
|
||||
my $nodes = 0;
|
||||
my $indices = 0;
|
||||
my $pretty = 0;
|
||||
|
||||
my $json = [];
|
||||
|
||||
GetOptions (
|
||||
'user:s' => \$user,
|
||||
'password:s' => \$pass,
|
||||
'url=s' => \$url,
|
||||
'cert-check!' => \$certcheck,
|
||||
'nodes' => \$nodes,
|
||||
'indices' => \$indices,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
if ($nodes and $indices){
|
||||
die "--nodes and --indices are mutually exclusive\n";
|
||||
}
|
||||
|
||||
my $uri = URI->new($url);
|
||||
|
||||
if (not defined $uri){
|
||||
die "$url is not a valid URL\n";
|
||||
}
|
||||
|
||||
# If connecting over http or is host is localhost
|
||||
# there's no need to check certificate
|
||||
if ($uri->scheme eq 'http' or $uri->host =~ m/^localhost|127\.0\.0/){
|
||||
$certcheck = 0;
|
||||
}
|
||||
|
||||
my $sslopts = {};
|
||||
if (not $certcheck){
|
||||
$sslopts = {
|
||||
verify_hostname => 0,
|
||||
SSL_verify_mode => 0
|
||||
}
|
||||
}
|
||||
|
||||
my $ua = LWP::UserAgent->new(
|
||||
ssl_opts => $sslopts
|
||||
);
|
||||
$ua->env_proxy;
|
||||
|
||||
if ($nodes){
|
||||
foreach (@{make_request('/_cat/nodes?format=json&full_id&h=ip,role,master,name,id,version')}){
|
||||
push @{$json}, {
|
||||
'{#ES_NODE_NAME}' => $_->{name},
|
||||
'{#ES_NODE_ROLE}' => $_->{role},
|
||||
'{#ES_NODE_ID}' => $_->{id},
|
||||
'{#ES_NODE_VERSION}' => $_->{version},
|
||||
'{#ES_NODE_MASTER}' => $_->{master}
|
||||
};
|
||||
}
|
||||
} elsif ($indices){
|
||||
foreach (@{make_request('/_cat/indices?format=json')}){
|
||||
push @{$json}, {
|
||||
'{#ES_INDEX_NAME}' => $_->{index},
|
||||
'{#ES_INDEX_STATUS}' => $_->{status},
|
||||
'{#ES_INDEX_UUID}' => $_->{uuid}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
||||
|
||||
sub make_request {
|
||||
my $path = shift;
|
||||
my $req_url = $url . $path;
|
||||
my $req = GET $req_url;
|
||||
if (defined $user and $user ne '' and defined $pass and $pass ne ''){
|
||||
$req->authorization_basic($user, $pass);
|
||||
}
|
||||
my $resp = $ua->request($req);
|
||||
die "Request to $req_url failed : " . $resp->message . "\n" if $resp->is_error;
|
||||
return from_json($resp->decoded_content);
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
$first = 1;
|
||||
|
||||
print "{\n";
|
||||
print "\t\"data\":[\n\n";
|
||||
use JSON;
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
my $cmd;
|
||||
my $re;
|
||||
|
@ -36,19 +35,15 @@ for (`$cmd`){
|
|||
chomp($t);
|
||||
$critical = $t if ($t =~ m/^\d+$/);
|
||||
}
|
||||
$fsname =~ s!/!\\/!g;
|
||||
|
||||
print "\t,\n" if not $first;
|
||||
$first = 0;
|
||||
|
||||
print "\t{\n";
|
||||
print "\t\t\"{#FSNAME}\":\"$fsname\",\n";
|
||||
print "\t\t\"{#FSTYPE}\":\"$fstype\"\n";
|
||||
print "\t\t\"{#FSDEVICE}\":\"$block\"\n";
|
||||
print "\t\t\"{#FSWARNTHRES}\":\"$warning\"\n";
|
||||
print "\t\t\"{#FSCRITTHRES}\":\"$critical\"\n";
|
||||
print "\t}\n";
|
||||
push @{$json->{data}}, {
|
||||
"{#FSNAME}" => $fsname,
|
||||
"{#FSTYPE}" => $fstype,
|
||||
"{#FSDEVICE}" => $block,
|
||||
"{#FSWARNTHRES}" => $warning,
|
||||
"{#FSCRITTHRES}" => $critical
|
||||
};
|
||||
}
|
||||
|
||||
print "\n\t]\n";
|
||||
print "}\n";
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
|
|
@ -9,6 +9,7 @@ my $json;
|
|||
@{$json->{data}} = ();
|
||||
|
||||
my $gluster = which('gluster');
|
||||
my $lock = '/var/lock/gluster-zabbix.lock';
|
||||
|
||||
unless($gluster){
|
||||
# Gluster is not installed, just return an empty JSON object
|
||||
|
@ -16,6 +17,10 @@ unless($gluster){
|
|||
exit(0);
|
||||
}
|
||||
|
||||
# Get an exclusive lock
|
||||
open(LOCK, ">$lock") || die "Can't open $lock";
|
||||
flock(LOCK, 2);
|
||||
|
||||
my $what = 'volumes';
|
||||
GetOptions(
|
||||
"what=s" => \$what,
|
||||
|
@ -110,6 +115,7 @@ else{
|
|||
exit(1);
|
||||
}
|
||||
|
||||
close(LOCK);
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
||||
|
|
18
zabbix_scripts/disco_httpd
Normal file
18
zabbix_scripts/disco_httpd
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use LWP::Simple;
|
||||
use JSON;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
my $status = get('http://127.0.0.1/server-status?auto');
|
||||
|
||||
if ($status){
|
||||
push @{$json->{data}}, {"{#HTTPD_STATUS_URI}" => 'http://127.0.0.1/server-status'};
|
||||
}
|
||||
|
||||
print to_json($json);
|
||||
exit(0);
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use Linux::LVM;
|
||||
use Zabbix::Agent::Addons::LVM;
|
||||
use JSON;
|
||||
|
||||
my $what = $ARGV[0];
|
||||
|
@ -10,17 +10,20 @@ open STDERR, '>/dev/null';
|
|||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
if ($what eq "volumes"){
|
||||
foreach my $group (get_volume_group_list()){
|
||||
my @vg = eval { get_volume_group_list() };
|
||||
|
||||
unless ($@){
|
||||
if ($what eq "volumes"){
|
||||
foreach my $group (@vg){
|
||||
my %lvs = get_logical_volume_information($group);
|
||||
foreach my $lv (keys %lvs){
|
||||
$lv = ($lv =~ m!^/dev/$group!) ? $lv : "/dev/$group/$lv";
|
||||
push @{$json->{data}}, { "{#LVMVOL}" => "$lv" };
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($what eq "snapshots"){
|
||||
foreach my $group (get_volume_group_list()){
|
||||
}
|
||||
elsif ($what eq "snapshots"){
|
||||
foreach my $group (@vg){
|
||||
my %lvs = get_logical_volume_information($group);
|
||||
foreach my $lv (keys %lvs){
|
||||
if (defined $lvs{$lv}->{allocated_to_snapshot}){
|
||||
|
@ -29,9 +32,9 @@ elsif ($what eq "snapshots"){
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($what eq "thin_pools"){
|
||||
foreach my $group (get_volume_group_list()){
|
||||
}
|
||||
elsif ($what eq "thin_pools"){
|
||||
foreach my $group (@vg){
|
||||
my %lvs = get_logical_volume_information($group);
|
||||
foreach my $lv (keys %lvs){
|
||||
if (defined $lvs{$lv}->{allocated_pool_data}){
|
||||
|
@ -40,19 +43,19 @@ elsif ($what eq "thin_pools"){
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($what eq "groups"){
|
||||
foreach my $group (get_volume_group_list()){
|
||||
push @{$json->{data}}, { "{#LVMGRP}" => $group };
|
||||
}
|
||||
}
|
||||
else{
|
||||
elsif ($what eq "groups"){
|
||||
foreach my $group (@vg){
|
||||
push @{$json->{data}}, { "{#LVMGRP}" => $group }; }
|
||||
}
|
||||
else{
|
||||
print <<"EOF";
|
||||
|
||||
Usage: $0 [volumes|snapshots|groups]
|
||||
Usage: $0 [volumes|snapshots|thin_pools|groups]
|
||||
|
||||
EOF
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
|
37
zabbix_scripts/disco_mpath_sudo
Normal file
37
zabbix_scripts/disco_mpath_sudo
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
|
||||
my $mpath = 1;
|
||||
my $pretty = 0;
|
||||
my $json = [];
|
||||
|
||||
GetOptions(
|
||||
"mpath" => \$mpath,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
my $multipath = which('multipath');
|
||||
|
||||
if (not defined $multipath){
|
||||
print to_json($json, { pretty => $pretty });
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my @dev = qx($multipath -l -v1);
|
||||
# If command failed (eg no /etc/multipath.conf), then return an empty result
|
||||
if ($? ne 0){
|
||||
print to_json($json, { pretty => $pretty });
|
||||
exit 1;
|
||||
}
|
||||
foreach (@dev){
|
||||
chomp;
|
||||
push @{$json}, { '{#MPATH_DEV}' => $_ };
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
||||
exit 0;
|
18
zabbix_scripts/disco_nginx
Executable file
18
zabbix_scripts/disco_nginx
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use LWP::Simple;
|
||||
use JSON;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
my $status = get('http://127.0.0.1/nginx-status');
|
||||
|
||||
if ($status){
|
||||
push @{$json->{data}}, {"{#NGINX_STATUS_URI}" => 'http://127.0.0.1/nginx-status'};
|
||||
}
|
||||
|
||||
print to_json($json);
|
||||
exit(0);
|
|
@ -1,15 +1,13 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use JSON;
|
||||
use Zabbix::Agent::Addons::UPS;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
if (system("upsc -l >/dev/null 2>&1") == 0){
|
||||
foreach my $ups (`upsc -l`){
|
||||
chomp($ups);
|
||||
foreach my $ups (Zabbix::Agent::Addons::UPS::list_ups()){
|
||||
push @{$json->{data}}, {"{#UPSNAME}" => $ups};
|
||||
}
|
||||
}
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
|
35
zabbix_scripts/disco_pmg_sudo
Normal file
35
zabbix_scripts/disco_pmg_sudo
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
|
||||
my $what = 'nodes';
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'what=s' => \$what,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $pmgsh = which('pmgsh');
|
||||
my $json = {};
|
||||
@{$json->{data}} = ();
|
||||
|
||||
unless($pmgsh){
|
||||
print to_json($json) . "\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($what eq 'domains'){
|
||||
my $domains = from_json(qx($pmgsh get /config/domains 2>/dev/null));
|
||||
foreach my $item (@{$domains}){
|
||||
push @{$json->{data}}, {
|
||||
'{#PMG_RELAY_DOMAIN}' => $item->{domain},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
73
zabbix_scripts/disco_pve_sudo
Normal file
73
zabbix_scripts/disco_pve_sudo
Normal file
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
use Sys::Hostname;
|
||||
|
||||
my $what = 'nodes';
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'what=s' => \$what,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $pvesh = which('pvesh');
|
||||
my $json = {};
|
||||
@{$json->{data}} = ();
|
||||
|
||||
unless($pvesh){
|
||||
print to_json($json) . "\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# Are we using the new pvesh for which we have to specify the output format ?
|
||||
my $pvesh_opt = (system("$pvesh get /version --output-format=json >/dev/null 2>&1") == 0) ? '--output-format=json' : '';
|
||||
|
||||
if ($what eq 'nodes'){
|
||||
my $cluster_status = from_json(qx($pvesh get /cluster/status $pvesh_opt 2>/dev/null));
|
||||
foreach my $item (@{$cluster_status}){
|
||||
next if ($item->{type} ne 'node');
|
||||
push @{$json->{data}}, {
|
||||
'{#PVE_NODE_NAME}' => $item->{name},
|
||||
'{#PVE_NODE_IP}' => $item->{ip},
|
||||
'{#PVE_NODE_ID}' => $item->{nodeid},
|
||||
'{#PVE_NODE_LOCAL}' => $item->{local}
|
||||
};
|
||||
}
|
||||
} elsif ($what eq 'guests'){
|
||||
my $guests = from_json(qx($pvesh get /cluster/resources --type=vm $pvesh_opt 2>/dev/null));
|
||||
foreach my $guest (@{$guests}){
|
||||
push @{$json->{data}}, {
|
||||
'{#PVE_GUEST_ID}' => $guest->{vmid},
|
||||
'{#PVE_GUEST_NODE}' => $guest->{node},
|
||||
'{#PVE_GUEST_TYPE}' => $guest->{type},
|
||||
'{#PVE_GUEST_NAME}' => $guest->{name},
|
||||
'{#PVE_GUEST_TEMPLATE}' => $guest->{template}
|
||||
};
|
||||
}
|
||||
} elsif ($what eq 'storage'){
|
||||
my $stores = from_json(qx($pvesh get /storage $pvesh_opt 2>/dev/null));
|
||||
foreach my $store (@{$stores}){
|
||||
push @{$json->{data}}, {
|
||||
'{#PVE_STOR_ID}' => $store->{storage},
|
||||
'{#PVE_STOR_TYPE}' => $store->{type},
|
||||
'{#PVE_STOR_STATUS}' => (($store->{disable}) ? 0 : 1),
|
||||
'{#PVE_STOR_SHARED}' => ($store->{shared} || 0),
|
||||
'{#PVE_STOR_CONTENT}' => $store->{content}
|
||||
};
|
||||
}
|
||||
} elsif ($what eq 'pools'){
|
||||
my $pools = from_json(qx($pvesh get /pools $pvesh_opt 2>/dev/null));
|
||||
foreach my $pool (@{$pools}){
|
||||
push @{$json->{data}}, {
|
||||
'{#PVE_POOL_ID}' => $pool->{poolid},
|
||||
'{#PVE_POOL_DESC}' => $pool->{comment}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
|
@ -1,23 +1,24 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use File::Which;
|
||||
use JSON;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
my $hpacucli = '/usr/sbin/hpacucli';
|
||||
my $cli = which('hpacucli') || which('ssacli');
|
||||
|
||||
# the hpacucli utility is needed
|
||||
unless (-x $hpacucli){
|
||||
# hpacucli or ssacli utility is needed
|
||||
if (not defined $cli){
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
open( HPACUCLI, "$hpacucli controller all show status|" )
|
||||
or die "An error occured while running $hpacucli: $!";
|
||||
open( CLI, "$cli controller all show status|" )
|
||||
or die "An error occured while running $cli: $!";
|
||||
|
||||
foreach my $line (<HPACUCLI>){
|
||||
foreach my $line (<CLI>){
|
||||
if ( $line =~ m/Another instance of hpacucli is running! Stop it first\./i ){
|
||||
die "Another instance of hpacucli is running\n";
|
||||
}
|
||||
|
@ -25,6 +26,6 @@ foreach my $line (<HPACUCLI>){
|
|||
push @{$json->{data}}, {"{#MODEL}" => $1, "{#SLOT}" => $2};
|
||||
}
|
||||
}
|
||||
close HPACUCLI;
|
||||
close CLI;
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
|
|
@ -6,11 +6,13 @@ use JSON;
|
|||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
open FILE, "< /proc/mdstat" or die "Can't open /proc/mdadm : $!";
|
||||
foreach my $line (<FILE>) {
|
||||
if (!-x '/usr/bin/systemd-detect-virt' || system('/usr/bin/systemd-detect-virt', '-qc') != 0){
|
||||
open FILE, "< /proc/mdstat" or die "Can't open /proc/mdadm : $!";
|
||||
foreach my $line (<FILE>) {
|
||||
next unless ($line =~ m/^(md\d+)+\s*:/);
|
||||
my ($md,undef,$status,$level) = split(/\ /, $line);
|
||||
push @{$json->{data}}, {"{#DEVICE}" => $md, "{#STATUS}" => $status, "{#LEVEL}" => $level};
|
||||
}
|
||||
}
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
|
34
zabbix_scripts/disco_samba_dc_sudo
Normal file
34
zabbix_scripts/disco_samba_dc_sudo
Normal file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
|
||||
my $what = 'ou';
|
||||
my $pretty = 0;
|
||||
my $json = [];
|
||||
|
||||
my $samba_tool = which('samba-tool');
|
||||
|
||||
if (not defined $samba_tool){
|
||||
print $json;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
GetOptions(
|
||||
'what=s' => \$what,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
if ($what eq 'ou'){
|
||||
foreach (qx($samba_tool ou list)){
|
||||
chomp;
|
||||
push @{$json}, {
|
||||
'{#SAMBA_OU}' => $_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
|
@ -1,22 +1,41 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use Config::Simple;
|
||||
use Getopt::Long;
|
||||
use JSON;
|
||||
|
||||
my $type = 'temp';
|
||||
GetOptions(
|
||||
"type:s" => \$type
|
||||
);
|
||||
|
||||
# empty means temp
|
||||
$type = ($type eq '') ? 'temp' : $type;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
open SENSORS, ('</etc/zabbix/sensors.conf') ||
|
||||
die "Couldn't open /etc/zabbix/sensors.conf: $!\n";
|
||||
my $cfg = new Config::Simple;
|
||||
$cfg->read('/etc/zabbix/sensors.ini');
|
||||
$cfg->syntax('ini');
|
||||
my %sensors = ();
|
||||
foreach my $k (keys %{$cfg->vars}){
|
||||
$k =~ s/\..*$//;
|
||||
$sensors{$k} = 1 unless $sensors{$k};
|
||||
}
|
||||
|
||||
|
||||
foreach (<SENSORS>){
|
||||
next unless (/^(\w+)(\s+)?=(\s+)?(.*)!(\-?\d+)!(\-?\d+)$/);
|
||||
my ($sensor,$threshigh,$threslow) = ($1,$5,$6);
|
||||
foreach my $k (keys %sensors){
|
||||
my $sensor = $cfg->get_block($k);
|
||||
next if ($type ne 'all' && $type ne $sensor->{type});
|
||||
push @{$json->{data}}, {
|
||||
"{#SENSORNAME}" => $sensor,
|
||||
"{#SENSORTHRESHIGH}" => $threshigh,
|
||||
"{#SENSORTHRESLOW}" => $threslow
|
||||
"{#SENSORNAME}" => $k,
|
||||
"{#SENSORDESC}" => $sensor->{description},
|
||||
"{#SENSORTHRESHIGH}" => $sensor->{threshold_high},
|
||||
"{#SENSORTHRESLOW}" => $sensor->{threshold_low},
|
||||
"{#SENSORTYPE}" => $sensor->{type},
|
||||
"{#SENSORUNIT}" => $sensor->{unit}
|
||||
};
|
||||
}
|
||||
close SENSORS;
|
||||
|
||||
print to_json($json);
|
||||
exit(0);
|
||||
|
|
|
@ -2,34 +2,13 @@
|
|||
|
||||
use warnings;
|
||||
use strict;
|
||||
use Zabbix::Agent::Addons::Disks;
|
||||
use JSON;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
opendir(my $dh, "/sys/block") or die "Couldn't open /sys/block: $!";
|
||||
my @blocks = grep { $_ !~ m/^\./ } readdir($dh);
|
||||
closedir($dh);
|
||||
foreach my $block (@blocks){
|
||||
my $removable = 0;
|
||||
my $size = 1;
|
||||
# Skip block we already know they won't support SMART
|
||||
next if ($block =~ m/^(ram|loop|md|dm\-)\d+/);
|
||||
if ( -e "/sys/block/$block/removable"){
|
||||
open REMOVABLE, "/sys/block/$block/removable";
|
||||
$removable = join "", <REMOVABLE>;
|
||||
close REMOVABLE;
|
||||
chomp($removable);
|
||||
next if ($removable eq '1');
|
||||
}
|
||||
if ( -e "/sys/block/$block/size"){
|
||||
open SIZE, "/sys/block/$block/size";
|
||||
$size = join "", <SIZE>;
|
||||
close SIZE;
|
||||
chomp($size);
|
||||
next if ($size eq '0');
|
||||
}
|
||||
next unless (system("/usr/sbin/smartctl -A /dev/$block >/dev/null 2>&1") == 0);
|
||||
foreach my $block (Zabbix::Agent::Addons::Disks::list_smart_hdd({ skip_remouvable => 1 })){
|
||||
push @{$json->{data}}, { "{#SMARTDRIVE}" => "/dev/$block" };
|
||||
}
|
||||
print to_json($json);
|
||||
|
|
18
zabbix_scripts/disco_squid
Normal file
18
zabbix_scripts/disco_squid
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use LWP::Simple;
|
||||
use JSON;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
my $status = get('http://127.0.0.1:3128/squid-internal-mgr/info');
|
||||
|
||||
if ($status){
|
||||
push @{$json->{data}}, {"{#SQUID_STATUS_URI}" => 'http://127.0.0.1:3128/squid-internal-mgr/info'};
|
||||
}
|
||||
|
||||
print to_json($json);
|
||||
exit(0);
|
61
zabbix_scripts/disco_stor_dev_sudo
Normal file
61
zabbix_scripts/disco_stor_dev_sudo
Normal file
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
use File::Which;
|
||||
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $smartctl = which('smartctl');
|
||||
my $json = [];
|
||||
|
||||
sub print_out {
|
||||
print to_json($json, { pretty => $pretty });
|
||||
}
|
||||
|
||||
if (not defined $smartctl){
|
||||
print_out();
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $smart_scan = from_json(qx($smartctl --scan-open --json=c));
|
||||
|
||||
if (not defined $smart_scan){
|
||||
print_out();
|
||||
exit 0;
|
||||
}
|
||||
|
||||
foreach my $device (@{$smart_scan->{devices}}){
|
||||
my ($model, $sn, $has_smart) = "";
|
||||
my $smart_info = from_json(qx($smartctl -i $device->{name} -d $device->{type} --json=c));
|
||||
|
||||
if (defined $smart_info){
|
||||
$model = $smart_info->{model_name};
|
||||
$sn = $smart_info->{serial_number};
|
||||
$has_smart = (
|
||||
$smart_info->{in_smartctl_database} or (
|
||||
defined $smart_info->{smart_support} and
|
||||
$smart_info->{smart_support}->{available} and
|
||||
$smart_info->{smart_support}->{enabled}
|
||||
)
|
||||
) ? 1 : 0;
|
||||
}
|
||||
|
||||
push @{$json}, {
|
||||
'{#STOR_DEV_NAME}' => $device->{name},
|
||||
'{#STOR_DEV_DESC}' => $device->{info_name},
|
||||
'{#STOR_DEV_TYPE}' => $device->{type},
|
||||
'{#STOR_DEV_PROTO}' => $device->{protocol},
|
||||
'{#STOR_DEV_MODEL}' => $model,
|
||||
'{#STOR_DEV_SN}' => $sn,
|
||||
'{#STOR_DEV_SMART}' => int $has_smart
|
||||
};
|
||||
}
|
||||
|
||||
print_out();
|
141
zabbix_scripts/disco_unifi
Executable file
141
zabbix_scripts/disco_unifi
Executable file
|
@ -0,0 +1,141 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Getopt::Long;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Cookies;
|
||||
use URI;
|
||||
use Data::Dumper;
|
||||
|
||||
umask 077;
|
||||
|
||||
my $user = 'zabbix';
|
||||
my $pass = 'secret';
|
||||
my $site = 'default';
|
||||
my $url = 'https://localhost:8443';
|
||||
my $certcheck = 1;
|
||||
my $what = 'devices';
|
||||
my $type = 'all';
|
||||
my $pretty = 0;
|
||||
|
||||
my $json = {};
|
||||
@{$json->{data}} = ();
|
||||
|
||||
GetOptions (
|
||||
'user=s' => \$user,
|
||||
'password|p=s' => \$pass,
|
||||
'site=s' => \$site,
|
||||
'url=s' => \$url,
|
||||
'cert-check!' => \$certcheck,
|
||||
'what=s' => \$what,
|
||||
'type:s' => \$type,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
# An empty type is the same as all
|
||||
$type = 'all' if ($type eq '');
|
||||
|
||||
# If connecting to localhost, no need to check certificate
|
||||
my $uri = URI->new($url);
|
||||
if ($uri->host =~ m/^localhost|127\.0\.0/){
|
||||
$certcheck = 0;
|
||||
}
|
||||
|
||||
my $site_id;
|
||||
my $resp;
|
||||
my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<);
|
||||
my $cj = HTTP::Cookies->new(
|
||||
file => "/tmp/.unifi_$username.txt",
|
||||
autosave => 1,
|
||||
ignore_discard => 1
|
||||
);
|
||||
|
||||
my $sslopts = {};
|
||||
if (not $certcheck){
|
||||
$sslopts = { verify_hostname => 0, SSL_verify_mode => 0 }
|
||||
}
|
||||
|
||||
my $ua = LWP::UserAgent->new(
|
||||
ssl_opts => $sslopts,
|
||||
cookie_jar => $cj
|
||||
);
|
||||
|
||||
# Check if we need to login
|
||||
$resp = $ua->get($url . '/api/self/sites');
|
||||
|
||||
if ($resp->is_error){
|
||||
# Login on the API
|
||||
$resp = $ua->post(
|
||||
$url . '/api/login',
|
||||
Content => to_json({ username => $user, password => $pass }),
|
||||
Content_Type => 'application/json;charset=UTF-8'
|
||||
);
|
||||
die "Login failed: " . $resp->message . "\n" if $resp->is_error;
|
||||
$resp = $ua->get($url . '/api/self/sites');
|
||||
die $resp->message . "\n" if $resp->is_error;
|
||||
}
|
||||
|
||||
foreach (@{from_json($resp->decoded_content)->{data}}){
|
||||
if ($_->{name} eq $site || $_->{desc} eq $site){
|
||||
$site_id = $_->{_id};
|
||||
# If site is referenced by description, translate it to name
|
||||
$site = $_->{name} if ($_->{name} ne $site);
|
||||
last;
|
||||
}
|
||||
}
|
||||
die "Site $site not found\n" unless ($site_id);
|
||||
|
||||
if ($what eq 'devices'){
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/device');
|
||||
die $resp->message . "\n" if $resp->is_error;
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
next if ($type ne 'all' && $entry->{type} ne $type);
|
||||
push @{$json->{data}}, {
|
||||
'{#UNIFI_DEV_ID}' => $entry->{device_id},
|
||||
'{#UNIFI_DEV_ADOPTED}' => $entry->{adopted},
|
||||
'{#UNIFI_DEV_MODEL}' => $entry->{model},
|
||||
'{#UNIFI_DEV_NAME}' => $entry->{name} || $entry->{mac},
|
||||
'{#UNIFI_DEV_MAC}' => $entry->{mac},
|
||||
'{#UNIFI_DEV_TYPE}' => $entry->{type}
|
||||
};
|
||||
}
|
||||
} elsif ($what eq 'stations'){
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/stat/sta');
|
||||
die $resp->message . "\n" if $resp->is_error;
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
# Ignore other sites
|
||||
next if ($entry->{site_id} ne $site_id);
|
||||
next if ($type eq 'wireless' and $entry->{is_wired} == JSON::true);
|
||||
next if ($type eq 'wired' and $entry->{is_wired} == JSON::false);
|
||||
push @{$json->{data}}, {
|
||||
'{#UNIFI_STA_ID}' => $entry->{_id},
|
||||
'{#UNIFI_STA_NAME}' => (defined $entry->{hostname}) ? $entry->{hostname} : $entry->{mac},
|
||||
'{#UNIFI_STA_MAC}' => $entry->{mac}
|
||||
};
|
||||
}
|
||||
} elsif ($what eq 'networks'){
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/rest/networkconf');
|
||||
die $resp->message . "\n" if $resp->is_error;
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
# Ignore other sites
|
||||
next if ($entry->{site_id} ne $site_id);
|
||||
next if ($type ne 'all' and $entry->{purpose} ne $type);
|
||||
push @{$json->{data}}, {
|
||||
'{#UNIFI_NET_ID}' => $entry->{_id},
|
||||
'{#UNIFI_NET_NAME}' => $entry->{name}
|
||||
};
|
||||
}
|
||||
} elsif ($what eq 'wlan') {
|
||||
$resp = $ua->get($url . '/api/s/' . $site . '/rest/wlanconf');
|
||||
die $resp->message . "\n" if $resp->is_error;
|
||||
foreach my $entry (@{from_json($resp->decoded_content)->{data}}){
|
||||
push @{$json->{data}}, {
|
||||
'{#UNIFI_WLAN_ID}' => $entry->{_id},
|
||||
'{#UNIFI_WLAN_NAME}' => $entry->{name}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
31
zabbix_scripts/disco_vdo_sudo
Normal file
31
zabbix_scripts/disco_vdo_sudo
Normal file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
|
||||
my $what = 'volumes';
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
'what=s' => \$what,
|
||||
'pretty' => \$pretty
|
||||
);
|
||||
|
||||
my $vdostats = which('vdostats');
|
||||
|
||||
if (defined $vdostats) {
|
||||
foreach my $line (qx($vdostats)) {
|
||||
if ($line =~ m|^/dev/mapper/([^\s]+)|) {
|
||||
push @{$json->{data}}, {
|
||||
'{#VDO_VOL}' => $1
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
print to_json($json, { pretty => $pretty }) . "\n";
|
77
zabbix_scripts/disco_zfs
Normal file
77
zabbix_scripts/disco_zfs
Normal file
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use File::Which;
|
||||
use Getopt::Long;
|
||||
|
||||
my $json;
|
||||
@{$json->{data}} = ();
|
||||
my $zpool = which('zpool');
|
||||
my $zfs = which('zfs');
|
||||
my $sanoid = which('sanoid');
|
||||
|
||||
if (not $zpool or not $zfs){
|
||||
print 'ZBX_NOTSUPPOTED';
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my $pools = 1;
|
||||
my $fs = 0;
|
||||
my $zvol = 0;
|
||||
my $snap = 0;
|
||||
my $sanoidmon = 0;
|
||||
my $arcstats = 0;
|
||||
my $pretty = 0;
|
||||
|
||||
GetOptions(
|
||||
"pools" => \$pools,
|
||||
"fs|filesystems" => \$fs,
|
||||
"zvols|volumes" => \$zvol,
|
||||
"snapshots" => \$snap,
|
||||
"sanoid" => \$sanoidmon,
|
||||
"arcstats" => \$arcstats,
|
||||
"pretty" => \$pretty
|
||||
);
|
||||
|
||||
if ($fs or $zvol or $snap or $sanoidmon or $arcstats){
|
||||
$pools = 0;
|
||||
}
|
||||
if ($pools + $fs + $zvol + $snap + $sanoidmon + $arcstats != 1){
|
||||
die "One and only one type of discovery should be provided\n";
|
||||
}
|
||||
if ($sanoidmon and not $sanoid){
|
||||
print to_json($json);
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($pools){
|
||||
foreach (qx($zpool list -H -o name)){
|
||||
chomp;
|
||||
push @{$json->{data}}, { '{#ZPOOL}' => $_ };
|
||||
}
|
||||
} elsif ($fs){
|
||||
foreach (qx($zfs list -H -o name -t filesystem)){
|
||||
chomp;
|
||||
push @{$json->{data}}, { '{#ZFS_FS}' => $_ };
|
||||
}
|
||||
} elsif ($zvol){
|
||||
foreach (qx($zfs list -H -o name -t volume)){
|
||||
chomp;
|
||||
push @{$json->{data}}, { '{#ZFS_ZVOL}' => $_ };
|
||||
}
|
||||
} elsif ($snap){
|
||||
foreach (qx($zfs list -H -o name -t snap)){
|
||||
chomp;
|
||||
# Remove @ as they are not allowed in item key names
|
||||
# They will be converted back to @ by check_zfs script
|
||||
$_ =~ s/\@/%40/g;
|
||||
push @{$json->{data}}, { '{#ZFS_SNAP}' => $_ };
|
||||
}
|
||||
} elsif ($sanoidmon){
|
||||
push @{$json->{data}}, { '{#ZFS_SANOID}' => $_ } foreach (qw(snapshot));
|
||||
} elsif ($arcstats){
|
||||
push @{$json->{data}}, { '{#ZFS_STATS}' => 'arcstats' };
|
||||
}
|
||||
print to_json($json, { pretty => $pretty });
|
63
zabbix_scripts/disco_zimbra_sudo
Normal file
63
zabbix_scripts/disco_zimbra_sudo
Normal file
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use JSON;
|
||||
use POSIX;
|
||||
use Getopt::Long;
|
||||
use Net::Domain qw(hostfqdn);
|
||||
use Data::Dumper;
|
||||
|
||||
my $json = [];
|
||||
|
||||
my $pretty = 0;
|
||||
my $services = 1;
|
||||
my $servers = 0;
|
||||
|
||||
GetOptions(
|
||||
"pretty" => \$pretty,
|
||||
"services" => \$services,
|
||||
"servers" => \$servers
|
||||
);
|
||||
|
||||
if ($servers) {
|
||||
$services = 0;
|
||||
}
|
||||
|
||||
my $uid = getuid();
|
||||
my $gid = getgid();
|
||||
my (undef,undef,$zimuid,$zimgid) = getpwnam('zimbra');
|
||||
|
||||
my $zmprov = '/opt/zimbra/bin/zmprov';
|
||||
my $hostname = hostfqdn();
|
||||
|
||||
# If there's no zimbra user or no zmcontrol, just return an empty list
|
||||
if (not defined $zimuid or not defined $zimgid or not -e $zmprov){
|
||||
print to_json($json);
|
||||
exit;
|
||||
}
|
||||
|
||||
# Switch to Zimbra user
|
||||
setuid($zimuid) if ($uid ne $zimuid);
|
||||
setgid($zimgid) if ($gid ne $zimgid);
|
||||
|
||||
if ($services){
|
||||
# zmconfigd is always enabled and should be running
|
||||
push @{$json}, {
|
||||
'{#ZM_SERVICE}' => 'zmconfigd'
|
||||
};
|
||||
foreach my $service (qx($zmprov getServer $hostname zimbraServiceEnabled)){
|
||||
if ($service =~ m/^zimbraServiceEnabled:\s+(\w+)/){
|
||||
push @{$json}, {
|
||||
'{#ZM_SERVICE}' => $1
|
||||
};
|
||||
}
|
||||
}
|
||||
} elsif ($servers){
|
||||
foreach my $server (qx($zmprov getAllServers)){
|
||||
chomp $server;
|
||||
push @{$json}, {
|
||||
'{#ZM_SERVER}' => $server
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
print to_json($json, { pretty => $pretty });
|
47
zabbix_scripts/util_convert_sensors_ini
Normal file
47
zabbix_scripts/util_convert_sensors_ini
Normal file
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Config::Simple '-strict';
|
||||
use JSON;
|
||||
|
||||
my $old = shift;
|
||||
$old ||= '/etc/zabbix/sensors.conf';
|
||||
my $new = '/etc/zabbix/sensors.ini';
|
||||
|
||||
my $sensors = {};
|
||||
|
||||
my $units = {
|
||||
temp => '°C',
|
||||
fan => 'rpm',
|
||||
power => 'W'
|
||||
};
|
||||
|
||||
open OLDSENSORS, ("<$old") ||
|
||||
die "Couldn't open $old: $!\n";
|
||||
|
||||
|
||||
foreach (<OLDSENSORS>){
|
||||
next unless (/^(\w+)(\s+)?=(\s+)?(.*)!(\-?\d+)!(\-?\d+)(!(\w+))?$/);
|
||||
my ($sensor,$cmd,$threshigh,$threslow,$type) = ($1,$4,$5,$6,$8);
|
||||
$type ||= 'temp';
|
||||
$sensors->{$sensor} = {
|
||||
description => $sensor,
|
||||
cmd => $cmd,
|
||||
threshold_high => $threshigh,
|
||||
threshold_low => $threslow,
|
||||
type => $type,
|
||||
unit => $units->{$type}
|
||||
};
|
||||
}
|
||||
|
||||
my $cfg = new Config::Simple(syntax => 'ini');
|
||||
|
||||
foreach my $k (keys %$sensors){
|
||||
$cfg->set_block($k, $sensors->{$k});
|
||||
}
|
||||
|
||||
$cfg->write($new);
|
||||
|
||||
rename $old, $old . '.bak';
|
403
zabbix_scripts/util_generate_sensors_ini
Executable file
403
zabbix_scripts/util_generate_sensors_ini
Executable file
|
@ -0,0 +1,403 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Config::Simple '-strict';
|
||||
use Getopt::Long;
|
||||
use File::Which;
|
||||
use File::Basename;
|
||||
use Zabbix::Agent::Addons::Disks;
|
||||
use Zabbix::Agent::Addons::UPS;
|
||||
|
||||
# Output file
|
||||
my $output = undef;
|
||||
# When a threshold can be automatically detected,
|
||||
# you may want to be notified before it's reached, so you can
|
||||
# set a margin which will be substracted from the real threshold
|
||||
my $temp_margin = '20';
|
||||
my $temp_hd_margin = '10';
|
||||
my $pwr_margin = '200';
|
||||
my $pwr_rel_margin = '20';
|
||||
# This value will be substracted from the higher threshold to define the low one
|
||||
# so you can have hysteresis to prevent flip-flop
|
||||
my $temp_hyst = '10';
|
||||
my $temp_hd_hyst = '5';
|
||||
my $temp_ups_hyst = '5';
|
||||
my $pwr_hyst = '200';
|
||||
my $pwr_rel_hyst = '10';
|
||||
|
||||
# Default threshold if not detected
|
||||
my $def_temp_thres_high = '50';
|
||||
my $def_hd_temp_thres_high = '50';
|
||||
my $def_ups_temp_thres_high = '40';
|
||||
my $def_fan_thres_high = '1000';
|
||||
my $def_fan_thres_low = '700';
|
||||
my $def_pwr_thres_high = '1000';
|
||||
my $def_pwr_rel_thres_high = '80';
|
||||
|
||||
GetOptions(
|
||||
"output=s" => \$output,
|
||||
"temp-margin=i" => \$temp_margin,
|
||||
"temp-hd-margin=i" => \$temp_hd_margin,
|
||||
"pwr-margin=i" => \$pwr_margin,
|
||||
"pwr-rel-margin=i" => \$pwr_rel_margin,
|
||||
"temp-hyst=i" => \$temp_hyst,
|
||||
"temp-hd-hyst=i" => \$temp_hd_hyst,
|
||||
"temp-ups-hyst=i" => \$temp_ups_hyst,
|
||||
"pwr-hyst=i" => \$pwr_hyst,
|
||||
"pwr-rel-hys=i" => \$pwr_rel_hyst
|
||||
);
|
||||
|
||||
sub usage(){
|
||||
print<<"_EOF";
|
||||
Usage: $0 --output=/etc/zabbix/sensors.ini
|
||||
_EOF
|
||||
}
|
||||
|
||||
unless ($output){
|
||||
usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Path
|
||||
my $ipmitool = which('ipmitool');
|
||||
my $smartctl = which('smartctl');
|
||||
my $lmsensor = which('sensors');
|
||||
my $upsc = which('upsc');
|
||||
|
||||
my $cfg = new Config::Simple(syntax => 'ini');
|
||||
|
||||
my $sensors = {};
|
||||
|
||||
# Try to detect IPMI sensors
|
||||
if ($ipmitool && -x $ipmitool){
|
||||
# First check for temperature sensors
|
||||
my @lines = qx($ipmitool sdr type Temperature 2>/dev/null);
|
||||
if ($? == 0){
|
||||
SENSOR: foreach my $l (@lines){
|
||||
chomp $l;
|
||||
# Looks like
|
||||
# Inlet Temp | 04h | ok | 7.1 | 25 degrees C
|
||||
if ($l !~ m/^(\w+[\s\w\/\-]+?\w+)\s*\|.*\|\s*([\w\.\s]+)\s*\|.*\|\s*([\-\w\.\s]+)$/){
|
||||
next SENSOR;
|
||||
}
|
||||
my $name = $1;
|
||||
my $sensor = {};
|
||||
|
||||
my @details = qx($ipmitool sdr get '$name' 2>/dev/null);
|
||||
if ($? != 0){
|
||||
print "Couldn't get detail for sensor $name\n";
|
||||
next SENSOR;
|
||||
}
|
||||
my $val = undef;
|
||||
foreach my $d (@details){
|
||||
chomp $d;
|
||||
if ($d =~ m/^\s*Sensor\sReading\s*:\s*(\-?\w+)/){
|
||||
$val = $1;
|
||||
print "Sensor $name has value: $val\n";
|
||||
if ($val !~ m/^\-?\d+$/){
|
||||
print "Skipping sensor $name, couldn't parse its value: $val\n";
|
||||
next SENSOR;
|
||||
}
|
||||
}
|
||||
elsif ($d =~ m/^\s*Upper\scritical\s*:\s*(\-?\d+(\.\d+))/){
|
||||
$sensor->{threshold_high} = $1-$temp_margin;
|
||||
}
|
||||
elsif ($d =~ m/^\s*Upper\snon\-critical\s*:\s*(\-?\d+(\.\d+))/){
|
||||
$sensor->{threshold_low} = $1-$temp_margin;
|
||||
}
|
||||
}
|
||||
# Another loop to check for Normal max if Upper critical wasn't found
|
||||
if (!$sensor->{threshold_high}){
|
||||
foreach my $d (@details){
|
||||
chomp $d;
|
||||
if ($d =~ m/^\s*Normal\sMaximum\s*:\s*(\-?\d+(\.\d+))/){
|
||||
$sensor->{threshold_high} = $1-$temp_margin;
|
||||
}
|
||||
}
|
||||
}
|
||||
next SENSOR unless $val;
|
||||
$sensor->{threshold_low} ||= ($sensor->{threshold_high}) ? $sensor->{threshold_high}-$temp_hyst : $def_temp_thres_high-$temp_hyst;
|
||||
$sensor->{threshold_high} ||= $def_temp_thres_high;
|
||||
$sensor->{threshold_high} =~ s/\.0+$//;
|
||||
$sensor->{threshold_low} =~ s/\.0+$//;
|
||||
$sensor->{description} = $name;
|
||||
$sensor->{type} = 'temp';
|
||||
$sensor->{unit} = '°C';
|
||||
$sensor->{cmd} = "$ipmitool sdr get '$name' 2>/dev/null | perl -ne 'if (/Sensor Reading\\s*:\\s*([^\\s]+)/) { print \"\$1\\n\"; last }'";
|
||||
my $id = sensor_name($name);
|
||||
$sensors->{$id} = $sensor;
|
||||
print "Found a temperature sensor using IPMI: $name\n";
|
||||
}
|
||||
}
|
||||
# Now check for Fan, nearly the same as Temp, but
|
||||
# * We try to detect the unit
|
||||
# * threshold handling is not the same
|
||||
@lines = qx($ipmitool sdr type Fan 2>/dev/null);
|
||||
if ($? == 0){
|
||||
SENSOR: foreach my $l (@lines){
|
||||
chomp $l;
|
||||
if ($l !~ m/^(\w+[\s\w]+?\w+)\s*\|.*\|\s*([\w\.\s]+)\s*\|.*\|\s*([\-\w\.\s]+)$/){
|
||||
next SENSOR;
|
||||
}
|
||||
my $name = $1;
|
||||
my $value = $3;
|
||||
my $sensor = {};
|
||||
|
||||
my @details = qx($ipmitool sdr get '$name' 2>/dev/null);
|
||||
if ($? != 0){
|
||||
print "Couldn't get detail for sensor $name\n";
|
||||
next SENSOR;
|
||||
}
|
||||
my $val = undef;
|
||||
foreach my $d (@details){
|
||||
chomp $d;
|
||||
if ($d =~ m/^\s*Sensor\sReading\s*:\s*(\d+(\.\d+)?)/){
|
||||
$val = $1;
|
||||
if ($val !~ m/^\d+(\.\d+)?$/){
|
||||
print "Skipping sensor $name, couldn't parse its value: $val\n";
|
||||
next SENSOR;
|
||||
}
|
||||
}
|
||||
elsif ($d =~ m/^\s*Lower\scritical\s*:\s*(\d+(\.\d+))/){
|
||||
$sensor->{threshold_low} = $1-$temp_margin;
|
||||
}
|
||||
elsif ($d =~ m/^\s*Lower\snon\-critical\s*:\s*(\d+(\.\d+))/){
|
||||
$sensor->{threshold_high} = $1-$temp_margin;
|
||||
}
|
||||
}
|
||||
next SENSOR unless $val;
|
||||
$sensor->{threshold_high} ||= $def_fan_thres_high;
|
||||
$sensor->{threshold_low} ||= $def_fan_thres_high-$temp_hyst;
|
||||
$sensor->{threshold_high} =~ s/\.0+$//;
|
||||
$sensor->{threshold_low} =~ s/\.0+$//;
|
||||
$sensor->{description} = $name;
|
||||
$sensor->{type} = 'fan';
|
||||
$sensor->{unit} = ($value =~ m/percent|%/ || $val < 100) ? '%' : 'rpm';
|
||||
$sensor->{cmd} = "$ipmitool sdr get '$name' 2>/dev/null | perl -ne 'if (/Sensor Reading\\s*:\\s*([^\\s]+)/) { print \"\$1\\n\"; last }'";
|
||||
my $id = sensor_name($name);
|
||||
$sensors->{$id} = $sensor;
|
||||
print "Found a fan sensor using IPMI: $name\n";
|
||||
}
|
||||
}
|
||||
# Now look for power information
|
||||
@lines = qx($ipmitool sdr type 'Current' 2>/dev/null);
|
||||
if ($? == 0){
|
||||
SENSOR: foreach my $l (@lines){
|
||||
chomp $l;
|
||||
if ($l !~ m/^(\w+[\s\w]+?\w+(\s%)?)\s*\|.*\|\s*([\w\.\s]+)\s*\|.*\|\s*([\-\w\.\s]+)$/){
|
||||
print "Skiping line $l\n";
|
||||
next SENSOR;
|
||||
}
|
||||
my $name = $1;
|
||||
my $value = $4;
|
||||
my $sensor = {};
|
||||
if ($name =~ m/(Power)|(Pwr)|(Consumption)|(PS\d+\sCurr\sOut)/i || $value =~ m/W(att)?/i){
|
||||
my @details = qx($ipmitool sdr get '$name' 2>/dev/null);
|
||||
if ($? != 0){
|
||||
print "Couldn't get detail for sensor $name\n";
|
||||
next SENSOR;
|
||||
}
|
||||
my $val = undef;
|
||||
my $unit = ($name =~ m/%/) ? '%' : 'Watt';
|
||||
foreach my $d (@details){
|
||||
chomp $d;
|
||||
if ($d =~ m/^\s*Sensor\sReading\s*:\s*(\w+)/){
|
||||
$val = $1;
|
||||
if ($val !~ m/^\d+$/){
|
||||
print "Skipping sensor $name, couldn't parse its value: $val\n";
|
||||
next SENSOR;
|
||||
}
|
||||
}
|
||||
elsif ($d =~ m/^\s*Upper\scritical\s*:\s*(\d+(\.\d+)?)/){
|
||||
$sensor->{threshold_high} = ($unit eq '%') ? $1-$pwr_rel_margin : $1-$pwr_margin;
|
||||
}
|
||||
elsif ($d =~ m/^\s*Upper\snon\-critical\s*:\s*(\d+(\.\d+)?)/){
|
||||
$sensor->{threshold_low} = ($unit eq '%') ? $1-$pwr_rel_margin : $1-$pwr_margin;
|
||||
}
|
||||
}
|
||||
next SENSOR unless $val;
|
||||
$sensor->{threshold_high} ||= ($unit eq '%') ? $def_pwr_rel_thres_high : $def_pwr_thres_high;
|
||||
$sensor->{threshold_low} ||= ($unit eq '%') ? $def_pwr_rel_thres_high-$pwr_rel_hyst : $def_pwr_thres_high-$pwr_hyst;
|
||||
$sensor->{threshold_high} =~ s/\.0+$//;
|
||||
$sensor->{threshold_low} =~ s/\.0+$//;
|
||||
$sensor->{description} = $name;
|
||||
$sensor->{type} = 'power';
|
||||
$sensor->{unit} = ($name =~ m/%/) ? '%' : 'Watt';
|
||||
$sensor->{cmd} = "$ipmitool sdr get '$name' 2>/dev/null | perl -ne 'if (/Sensor Reading\\s*:\\s*([^\\s]+)/) { print \"\$1\\n\"; last }'";
|
||||
my $id = sensor_name($name);
|
||||
$sensors->{$id} = $sensor;
|
||||
print "Found a power sensor using IPMI: $name\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Try to detect lm_sensors, using the sensors command
|
||||
if ($lmsensor && -x $lmsensor){
|
||||
my @lines = qx($lmsensor);
|
||||
if ($? == 0){
|
||||
SENSOR: foreach my $l (@lines){
|
||||
chomp $l;
|
||||
# Looks like
|
||||
# temp1: +27.8°C (crit = +119.0°C)
|
||||
# or
|
||||
# Core 0: +36.0°C (high = +80.0°C, crit = +100.0°C)
|
||||
if ($l !~ m/^(\w+[\s\w]+?):\s*\+?(\d+)(\.\d+)?°C\s*(.*)$/){
|
||||
next SENSOR;
|
||||
}
|
||||
my $name = $1;
|
||||
my $val = $2;
|
||||
my $thr = $4;
|
||||
my $sensor = {};
|
||||
|
||||
if ($val !~ m/^\-?\d+$/){
|
||||
print "Skipping sensor $name, couldn't parse its value: $val\n";
|
||||
next SENSOR;
|
||||
}
|
||||
|
||||
if ($name =~ m/^Core\s+\d+/){
|
||||
print "Skipping individual core sensor $name\n";
|
||||
next SENSOR;
|
||||
}
|
||||
|
||||
if ($thr =~ m/high\s+=\s+\+(\d+(\.\d+)?)/){
|
||||
$sensor->{threshold_high} = $1;
|
||||
}
|
||||
elsif ($thr =~ m/^crit\s+=\s+\+(\d+(\.\d+)?)/){
|
||||
$sensor->{threshold_high} = $1 - $temp_margin;
|
||||
}
|
||||
|
||||
next SENSOR unless $val;
|
||||
$sensor->{threshold_low} ||= ($sensor->{threshold_high}) ? $sensor->{threshold_high}-$temp_hyst : $def_temp_thres_high-$temp_hyst;
|
||||
$sensor->{threshold_high} ||= $def_temp_thres_high;
|
||||
$sensor->{threshold_high} =~ s/\.0+$//;
|
||||
$sensor->{threshold_low} =~ s/\.0+$//;
|
||||
$sensor->{description} = $name;
|
||||
$sensor->{type} = 'temp';
|
||||
$sensor->{unit} = '°C';
|
||||
$sensor->{cmd} = "$lmsensor | perl -ne 'if (/^$name:\\s*\\+(\\d+)/) { print \"\$1\\n\"; last }'";
|
||||
my $id = sensor_name($name);
|
||||
$sensors->{$id} = $sensor;
|
||||
print "Found a temperature sensor using lm_sensors: $name\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Now, try to detect smart capable HDD
|
||||
if ($smartctl && -x $smartctl){
|
||||
foreach my $block (Zabbix::Agent::Addons::Disks::list_smart_hdd({ skip_remouvable => 1 })){
|
||||
my @lines = qx($smartctl -A /dev/$block);
|
||||
next if ($? != 0);
|
||||
foreach my $l (@lines){
|
||||
if ($l =~ /(Temperature_Celsius|Airflow_Temperature_Cel)/){
|
||||
$sensors->{$block} = {
|
||||
description => "$block temperature",
|
||||
threshold_low => $def_hd_temp_thres_high-$temp_hd_hyst,
|
||||
threshold_high => $def_hd_temp_thres_high,
|
||||
type => 'temp',
|
||||
unit => '°C',
|
||||
cmd => "$smartctl -A /dev/$block | perl -ne 'if (/Temperature_Celsius(\\s+[^\\s]+){7}\\s+(\\d+(\\.\\d+)?)/) { print \"\$2\\n\"; last }'"
|
||||
};
|
||||
print "Found a temperature sensor using smartctl: $block\n";
|
||||
last;
|
||||
}
|
||||
# Format found on some NVMe SSD
|
||||
elsif ($l =~ /Temperature:\s+(\d+(\.\d+)?)\sCelsius/){
|
||||
$sensors->{$block} = {
|
||||
description => "$block temperature",
|
||||
threshold_low => $def_hd_temp_thres_high-$temp_hd_hyst,
|
||||
threshold_high => $def_hd_temp_thres_high,
|
||||
type => 'temp',
|
||||
unit => '°C',
|
||||
cmd => "$smartctl -A /dev/$block | perl -ne 'if (/Temperature:\\s+(\\d+(\\.\\d+)?)/) { print \"\$1\\n\"; last }'"
|
||||
};
|
||||
print "Found a temperature sensor using smartctl: $block\n";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
# Some LSI based hardware RAID controller can report HDD temp
|
||||
if (-e '/dev/megaraid_sas_ioctl_node'){
|
||||
# Only check for the firsts 26 drives
|
||||
foreach my $i (0..25){
|
||||
my @res = qx($smartctl -d megaraid,$i -A /dev/sda);
|
||||
next if ($? != 0);
|
||||
foreach my $l (@res){
|
||||
if ($l =~ m/Drive\sTrip\sTemperature:\s+(\d+)\s/){
|
||||
$sensors->{'sda-' . $i} = {
|
||||
description => "Temperature for disk No $i on sda",
|
||||
type => 'temp',
|
||||
threshold_high => $1-$temp_hd_margin,
|
||||
threshold_low => $1-$temp_hd_margin-$temp_hd_hyst,
|
||||
unit => '°C',
|
||||
cmd => "$smartctl -A -d megaraid,$i /dev/sda | grep 'Current Drive Temperature' | awk '{print \$4}'"
|
||||
};
|
||||
print "Found a temperature sensor using smartctl (megaraid): sda-$i\n";
|
||||
last;
|
||||
}
|
||||
elsif ($l =~ /(Temperature_Celsius|Airflow_Temperature_Cel)/){
|
||||
$sensors->{'sda-' . $i} = {
|
||||
description => "Temperature for disk No $i on sda",
|
||||
threshold_low => $def_hd_temp_thres_high-$temp_hd_hyst,
|
||||
threshold_high => $def_hd_temp_thres_high,
|
||||
type => 'temp',
|
||||
unit => '°C',
|
||||
cmd => "$smartctl -A -d megaraid,$i /dev/sda | perl -ne 'if (/(Temperature_Celsius|Airflow_Temperature_Cel)(\\s+[^\\s]+){7}\\s+(\\d+)/) { print \"\$3\\n\"; last }'"
|
||||
};
|
||||
print "Found a temperature sensor using smartctl (megaraid): sda-$i\n";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Now check UPS
|
||||
if ($upsc && -x $upsc){
|
||||
foreach my $ups (Zabbix::Agent::Addons::UPS::list_ups()){
|
||||
my @lines = qx($upsc $ups);
|
||||
next if ($? != 0);
|
||||
foreach my $l (@lines){
|
||||
if ($l =~ m/^ups\.temperature:\s+(\d+(\.\d+)?)/){
|
||||
$sensors->{'ups_' . lc $ups . '_temp'} = {
|
||||
description => "ups temperature for $ups",
|
||||
type => 'temp',
|
||||
threshold_high => $def_ups_temp_thres_high,
|
||||
threshold_low => $def_ups_temp_thres_high-$temp_ups_hyst,
|
||||
unit => '°C',
|
||||
cmd => "$upsc $ups ups.temperature 2>/dev/null"
|
||||
};
|
||||
print "Found a temperature sensor for ups $ups\n";
|
||||
last;
|
||||
}
|
||||
elsif ($l =~ m/^ups\.load:\s+(\d+(\.\d+)?)/){
|
||||
$sensors->{'ups_' . lc $ups . '_load'} = {
|
||||
description => "ups load for $ups",
|
||||
type => 'power',
|
||||
threshold_high => $def_pwr_rel_thres_high,
|
||||
threshold_low => $def_pwr_rel_thres_high-$pwr_rel_hyst,
|
||||
unit => '%',
|
||||
cmd => "$upsc $ups ups.load 2>/dev/null"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# TODO: add support for lm sensors, but its ouput is harder to parse
|
||||
foreach my $s (sort keys %$sensors){
|
||||
$cfg->set_block($s, $sensors->{$s});
|
||||
}
|
||||
|
||||
$cfg->write($output);
|
||||
|
||||
# Take a sensor description and return a suitable string as sensor ID
|
||||
sub sensor_name{
|
||||
my $desc = shift;
|
||||
my $id = lc $desc;
|
||||
$id =~ s/[^\w]/_/g;
|
||||
$id =~ s/%/percent/g;
|
||||
$id =~ s/_rpm$//;
|
||||
return $id;
|
||||
}
|
27
zabbix_scripts/util_populate_pve_cache
Normal file
27
zabbix_scripts/util_populate_pve_cache
Normal file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use JSON;
|
||||
|
||||
# Ensure data are fresh in the cache for Zabbix to pick them quickly
|
||||
# You can add this script in a cron job every 5 min for example, so the cache will always be fresh
|
||||
# for Zabbix Agent can run check_pve_sudo quickly
|
||||
|
||||
qx(/var/lib/zabbix/bin/check_pve_sudo --cluster --cache=120);
|
||||
|
||||
my $nodes = from_json(qx(/var/lib/zabbix/bin/disco_pve_sudo --what=nodes));
|
||||
foreach my $node (@{$nodes->{data}}){
|
||||
qx(/var/lib/zabbix/bin/check_pve_sudo --node=$node->{'{#PVE_NODE_NAME}'} --cache=120);
|
||||
}
|
||||
my $pools = from_json(qx(/var/lib/zabbix/bin/disco_pve_sudo --what=pools));
|
||||
foreach my $pool (@{$pools->{data}}){
|
||||
qx(/var/lib/zabbix/bin/check_pve_sudo --pool=$pool->{'{#PVE_POOL_ID}'} --cache=120);
|
||||
}
|
||||
my $storages = from_json(qx(/var/lib/zabbix/bin/disco_pve_sudo --what=storage));
|
||||
foreach my $stor (@{$storages->{data}}){
|
||||
qx(/var/lib/zabbix/bin/check_pve_sudo --storage=$stor->{'{#PVE_STOR_ID}'} --cache=120);
|
||||
}
|
||||
my $guests = from_json(qx(/var/lib/zabbix/bin/disco_pve_sudo --what=guests));
|
||||
foreach my $guest (@{$guests->{data}}){
|
||||
qx(/var/lib/zabbix/bin/check_pve_sudo --guest=$guest->{'{#PVE_GUEST_ID}'} --cache=120);
|
||||
}
|
||||
|
923
zabbix_templates/Template_App_BackupPC.xml
Normal file
923
zabbix_templates/Template_App_BackupPC.xml
Normal file
|
@ -0,0 +1,923 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-09-22T16:02:43Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_BackupPC</template>
|
||||
<name>Template_App_BackupPC</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<items>
|
||||
<item>
|
||||
<name>BackupPC: General info</name>
|
||||
<key>backuppc.general</key>
|
||||
<delay>15m</delay>
|
||||
<history>0</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Total number of backups</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[bkp]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>!backup(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bkp</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Total full size</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[full_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.full_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Total history size</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[history_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.history_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Total number of hosts</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[hosts]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>!host(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.hosts</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Global perf score</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[perf]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.perf</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Global compression ratio</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[ratio]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.ratio</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>BackupPC: Total size</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.general[total_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.total_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.general</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>Number of BackupPC processes</name>
|
||||
<key>proc.num[,backuppc,,BackupPC]</key>
|
||||
<delay>30m</delay>
|
||||
<history>60d</history>
|
||||
<trends>0</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>Number of raidsync processes</name>
|
||||
<key>proc.num[,root,,BackupPC_raidsync]</key>
|
||||
<delay>10m</delay>
|
||||
<history>60d</history>
|
||||
<trends>0</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{sum({$EXT_BACKUPS})}<1 and {$EXT_BACKUPS} > 0</expression>
|
||||
<name>No recent copy on external support</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
</items>
|
||||
<discovery_rules>
|
||||
<discovery_rule>
|
||||
<name>BackupPC: Entity discovery</name>
|
||||
<key>backuppc.entity.discovery[]</key>
|
||||
<delay>2h</delay>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Number of backups for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},bkp]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bkp</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Sum of last full sizes for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},full_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>o</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.full_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Sum of history sizes for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},history_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>o</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.history_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Number of backed up hosts for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},hosts]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.hosts</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Performance indicator for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},perf]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>!h/j</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.perf</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Compression ratio for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},ratio]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>%</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.ratio</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Total backups size for {#BPC_ENTITY}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>o</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Info for entity {#BPC_ENTITY}</name>
|
||||
<key>backuppc.entity[{#BPC_ENTITY}]</key>
|
||||
<delay>1h</delay>
|
||||
<history>0</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<graph_prototypes>
|
||||
<graph_prototype>
|
||||
<name>BackupPC: Entity {#BPC_ENTITY}: Compression ratio and perf</name>
|
||||
<ymin_type_1>FIXED</ymin_type_1>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<drawtype>GRADIENT_LINE</drawtype>
|
||||
<color>43A047</color>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},size]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<drawtype>BOLD_LINE</drawtype>
|
||||
<color>FF0000</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},ratio]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<drawtype>DASHED_LINE</drawtype>
|
||||
<color>0040FF</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},perf]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph_prototype>
|
||||
<graph_prototype>
|
||||
<name>BackupPC: Entity {#BPC_ENTITY}: Full / History sizes</name>
|
||||
<type>STACKED</type>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<color>4000FF</color>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},full_size]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<color>4DD0E1</color>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.entity[{#BPC_ENTITY},history_size]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph_prototype>
|
||||
</graph_prototypes>
|
||||
</discovery_rule>
|
||||
<discovery_rule>
|
||||
<name>BackupPC: Hosts discovery</name>
|
||||
<key>backuppc.host.discovery[]</key>
|
||||
<delay>2h;50s/1-7,00:00-24:00</delay>
|
||||
<filter>
|
||||
<evaltype>OR</evaltype>
|
||||
</filter>
|
||||
<lifetime>15d</lifetime>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Last backup age</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},age]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>s</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.age</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: Info de {#BPCHOST}</name>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
<delay>30m</delay>
|
||||
<history>0</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Number of backups</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},bkp]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>!backups</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bkp</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackuPPC: {#BPCHOST}: Compression ratio of last backup</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},comp_ratio]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>%</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.comp_ratio</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Last backup duration</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},duration]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>s</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.duration</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Backups status</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},enabled]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.enabled</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Number of errors on last backup</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},errors]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>!errors</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.errors</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Last full backup size</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},full_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.full_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: History size</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},history_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.history_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: New file size in last backup</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},new_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.new_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Average new sizes</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},new_size_avg]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.new_size_avg</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Median for new files sizes</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},new_size_median]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.new_size_median</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: First quartile of new sizes</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},new_size_q1]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.new_size_q1</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Third quartile of new sizes</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},new_size_q3]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.new_size_q3</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>BackupPC: {#BPCHOST}: Total backups size</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>backuppc.host[{#BPCHOST},total_size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<trends>1095d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>BackupPC</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.total_size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>backuppc.host[{#BPCHOST},all]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{Template_App_BackupPC:backuppc.host[{#BPCHOST},age].last(0)}>{#BPCNOBACKUPWARNING}*24*3600 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},enabled].last()}=1</expression>
|
||||
<name>No backup for {#BPCHOST} since {ITEM.LASTVALUE1}</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger_prototype>
|
||||
<trigger_prototype>
|
||||
<expression>{Template_App_BackupPC:backuppc.host[{#BPCHOST},enabled].last()}=1 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},bkp].last()}>4 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} > ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q3].last()} + ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q3].last()} - {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q1].last()}) * 1.5) and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} > {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_avg].last()}*{#BPC_TOO_BIG_FACTOR} and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 7 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 1 and ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 2 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].time()} > {$BPC_SIZE_WARN_FROM_HOUR})</expression>
|
||||
<recovery_mode>RECOVERY_EXPRESSION</recovery_mode>
|
||||
<recovery_expression>{Template_App_BackupPC:backuppc.host[{#BPCHOST},enabled].last()}=0 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},bkp].last()}<=4 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} <= ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q3].last()} + ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q3].last()} - {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q1].last()}) * 1.5) or {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} <= {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_avg].last()}*{#BPC_TOO_BIG_FACTOR}</recovery_expression>
|
||||
<name>Suspiciously big ({ITEM.VALUE3}) backup for {#BPCHOST}</name>
|
||||
<priority>INFO</priority>
|
||||
</trigger_prototype>
|
||||
<trigger_prototype>
|
||||
<expression>{#BPC_TOO_SMALL_FACTOR}>0 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},enabled].last()}=1 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},bkp].last()}>4 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} < ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q1].last()} - ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q3].last()} - {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q1].last()}) * 1.5) and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} < {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_avg].last()}/{#BPC_TOO_SMALL_FACTOR} and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 6 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 7 and {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 1 and ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].dayofweek()} <> 2 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].time()} > {$BPC_SIZE_WARN_FROM_HOUR})</expression>
|
||||
<recovery_mode>RECOVERY_EXPRESSION</recovery_mode>
|
||||
<recovery_expression>{#BPC_TOO_SMALL_FACTOR}<0 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},enabled].last()}=0 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},bkp].last()}<=4 or {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} >= ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q1].last()} - ({Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q3].last()} - {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_q1].last()}) * 1.5) or {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size].last()} >= {Template_App_BackupPC:backuppc.host[{#BPCHOST},new_size_avg].last()}/{#BPC_TOO_SMALL_FACTOR}</recovery_expression>
|
||||
<name>Suspiciously small ({ITEM.VALUE3}) backups for {#BPCHOST}</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger_prototype>
|
||||
<trigger_prototype>
|
||||
<expression>{Template_App_BackupPC:backuppc.host[{#BPCHOST},errors].last(0)}>{#BPCMAXERROR} and {Template_App_BackupPC:backuppc.host[{#BPCHOST},enabled].last()}=1</expression>
|
||||
<name>{ITEM.LASTVALUE1} (xfer) in last backup of {#BPCHOST}</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
<graph_prototypes>
|
||||
<graph_prototype>
|
||||
<name>BackupPC: Host {#BPCHOST}: Compression ratio and perf</name>
|
||||
<ymin_type_1>FIXED</ymin_type_1>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<drawtype>GRADIENT_LINE</drawtype>
|
||||
<color>43A047</color>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.host[{#BPCHOST},total_size]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<drawtype>BOLD_LINE</drawtype>
|
||||
<color>FF0000</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.host[{#BPCHOST},comp_ratio]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<color>7E57C2</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.host[{#BPCHOST},duration]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph_prototype>
|
||||
<graph_prototype>
|
||||
<name>BackupPC: Host {#BPCHOST}: Full / History sizes</name>
|
||||
<type>STACKED</type>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<color>4000FF</color>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.host[{#BPCHOST},full_size]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<color>4DD0E1</color>
|
||||
<item>
|
||||
<host>Template_App_BackupPC</host>
|
||||
<key>backuppc.host[{#BPCHOST},history_size]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph_prototype>
|
||||
</graph_prototypes>
|
||||
<request_method>POST</request_method>
|
||||
</discovery_rule>
|
||||
</discovery_rules>
|
||||
<macros>
|
||||
<macro>
|
||||
<macro>{$BPC_SIZE_WARN_FROM_HOUR}</macro>
|
||||
<value>080000</value>
|
||||
<description>Size alerts will only start after this hour</description>
|
||||
</macro>
|
||||
<macro>
|
||||
<macro>{$EXT_BACKUPS}</macro>
|
||||
<value>0</value>
|
||||
<description>If set to a positive duration, can alert if no raidsync backups has been made recently</description>
|
||||
</macro>
|
||||
</macros>
|
||||
</template>
|
||||
</templates>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{Template_App_BackupPC:proc.num[,backuppc,,BackupPC].sum(#2)}=0 and {Template_App_BackupPC:proc.num[,root,,BackupPC_raidsync].sum(#2)}=0</expression>
|
||||
<name>BackupPC isn't running</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</zabbix_export>
|
113
zabbix_templates/Template_App_DRBD.xml
Normal file
113
zabbix_templates/Template_App_DRBD.xml
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-06-19T12:07:47Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_DRBD</template>
|
||||
<name>Template_App_DRBD</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>DRBD</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<discovery_rules>
|
||||
<discovery_rule>
|
||||
<name>DRBD resources</name>
|
||||
<key>drbd.resource.discovery[]</key>
|
||||
<delay>30m</delay>
|
||||
<lifetime>2d</lifetime>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>DRBD: {#DRBD_RES_NAME} connexion status</name>
|
||||
<key>drbd.resource.status[{#DRBD_RES_NAME},cstate]</key>
|
||||
<delay>5m</delay>
|
||||
<history>180d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>CHAR</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>DRBD</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{str(Connected)}=0 and {str(SyncSource)}=0 and
|
||||
{str(SyncTarget)}=0</expression>
|
||||
<name>DRBD: ({#DRBD_RES_NAME}): connexion is not established</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>DRBD: {#DRBD_RES_NAME} data status</name>
|
||||
<key>drbd.resource.status[{#DRBD_RES_NAME},dstate]</key>
|
||||
<delay>5m</delay>
|
||||
<history>180d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>CHAR</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>DRBD</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{str(UpToDate)}=0</expression>
|
||||
<name>DRBD ({#DRBD_RES_NAME}): data is not up to date</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>DRBD: {#DRBD_RES_NAME} role</name>
|
||||
<key>drbd.resource.status[{#DRBD_RES_NAME},role]</key>
|
||||
<delay>5m</delay>
|
||||
<history>180d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>CHAR</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>DRBD</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{diff()}=1</expression>
|
||||
<name>DRBD ({#DRBD_RES_NAME}) node role has changed</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<request_method>POST</request_method>
|
||||
</discovery_rule>
|
||||
</discovery_rules>
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
610
zabbix_templates/Template_App_Docker.yaml
Normal file
610
zabbix_templates/Template_App_Docker.yaml
Normal file
|
@ -0,0 +1,610 @@
|
|||
zabbix_export:
|
||||
version: '5.4'
|
||||
date: '2022-01-20T13:55:05Z'
|
||||
groups:
|
||||
-
|
||||
uuid: 7df96b18c230490a9a0a9e2307226338
|
||||
name: Templates
|
||||
templates:
|
||||
-
|
||||
uuid: 722c34dae28f471b992685f75b217e84
|
||||
template: Template_App_Docker
|
||||
name: Template_App_Docker
|
||||
groups:
|
||||
-
|
||||
name: Templates
|
||||
items:
|
||||
-
|
||||
uuid: b35116a368e94b0698951010ddb496b5
|
||||
name: 'Docker: Number of paused container'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[global,ContainersPaused]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: '!container(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.info.ContainersPaused
|
||||
master_item:
|
||||
key: 'container.docker.check[global]'
|
||||
-
|
||||
uuid: ff406b09a49f42ef80e004f7b8737c9b
|
||||
name: 'Docker: Number of running container'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[global,ContainersRunning]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: '!container(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.info.ContainersRunning
|
||||
master_item:
|
||||
key: 'container.docker.check[global]'
|
||||
triggers:
|
||||
-
|
||||
uuid: 85e456243c714349b34ff6504d122004
|
||||
expression: 'change(/Template_App_Docker/container.docker.check[global,ContainersRunning])=1'
|
||||
name: 'Number of running containers changed to {ITEM.LASTVALUE1}'
|
||||
priority: INFO
|
||||
-
|
||||
uuid: 69c12d97c6604c608fba4d2c0d4875bb
|
||||
name: 'Docker: Number of stopped container'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[global,ContainersStopped]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: '!container(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.info.ContainersStopped
|
||||
master_item:
|
||||
key: 'container.docker.check[global]'
|
||||
-
|
||||
uuid: c6831879964a4a3a90fc82530e6a0d43
|
||||
name: 'Docker: Number of containers'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[global,Containers]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: '!container(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.info.Containers
|
||||
master_item:
|
||||
key: 'container.docker.check[global]'
|
||||
-
|
||||
uuid: 1da51785c3d34faf8ba7ab17d0b46b38
|
||||
name: 'Docker: Live restore status'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[global,LiveRestoreEnabled]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.info.LiveRestoreEnabled
|
||||
master_item:
|
||||
key: 'container.docker.check[global]'
|
||||
triggers:
|
||||
-
|
||||
uuid: 85a2fc38a6bb42e183de3d4687f466e8
|
||||
expression: 'last(/Template_App_Docker/container.docker.check[global,LiveRestoreEnabled])<>"true" and {$DOCKER_WARN_NO_LIVE_RESTORE}=1'
|
||||
name: 'Docker live restore isn''t enabled'
|
||||
priority: WARNING
|
||||
-
|
||||
uuid: ab2d3bd636964a21b764b2f33f2e109e
|
||||
name: 'Docker: server version'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[global,ServerVersion]'
|
||||
delay: '0'
|
||||
history: 15d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.info.ServerVersion
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[global]'
|
||||
triggers:
|
||||
-
|
||||
uuid: 8c535ff0d73240c395226ee91a8096c4
|
||||
expression: '(last(/Template_App_Docker/container.docker.check[global,ServerVersion])<>last(/Template_App_Docker/container.docker.check[global,ServerVersion],#2))=1'
|
||||
name: 'Docker version changed ({ITEM.LASTVALUE1})'
|
||||
priority: WARNING
|
||||
-
|
||||
uuid: d5c424dc767c4a5ea1ee441e76770411
|
||||
name: 'Docker global info'
|
||||
key: 'container.docker.check[global]'
|
||||
delay: 5m
|
||||
history: '0'
|
||||
trends: '0'
|
||||
value_type: TEXT
|
||||
discovery_rules:
|
||||
-
|
||||
uuid: e459f638e15f495db3e4a9060e60f7c8
|
||||
name: 'Docker: container discovery'
|
||||
key: 'container.docker.discovery[containers]'
|
||||
delay: 15m
|
||||
lifetime: 7d
|
||||
item_prototypes:
|
||||
-
|
||||
uuid: 7f3fddee7aed48c8acc26e9aa98df298
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO Read'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIORead]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: B/s
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.BlockIORead
|
||||
-
|
||||
type: CHANGE_PER_SECOND
|
||||
parameters:
|
||||
- ''
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 27f4e3e3a33c412ead03200de17bc9b5
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO Write'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIOWrite]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: B/s
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.BlockIOWrite
|
||||
-
|
||||
type: CHANGE_PER_SECOND
|
||||
parameters:
|
||||
- ''
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: f59ee387b12740fc90ff6d990422e92d
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: CPU'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
value_type: FLOAT
|
||||
units: '%'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.CPUPerc
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: d2bdccc7bf8a49c6a2c584a5394a0c27
|
||||
expression: 'avg(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc],1h)>{$DOCKER_CPU_PCT_WARN:"{#DOCKER_CONTAINER_NAME}"}'
|
||||
recovery_mode: RECOVERY_EXPRESSION
|
||||
recovery_expression: 'avg(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc],1h)<({$DOCKER_CPU_PCT_WARN:"{#DOCKER_CONTAINER_NAME}"}-2) or avg(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc],5m)<({$DOCKER_CPU_PCT_WARN:"{#DOCKER_CONTAINER_NAME}"}/3)'
|
||||
name: 'Container {#DOCKER_CONTAINER_NAME} CPU usage is {ITEM.VALUE1}'
|
||||
priority: INFO
|
||||
-
|
||||
uuid: f56ddbaef3af4fa898ae2403a812db3c
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Dead'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Dead]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.inspect.State.Dead
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: e09f311feb1749cc88e8c51c8425c324
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Error'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Error]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.inspect.State.Error
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: b75ac0b193d2451e8ee3ce0950b7b07a
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Image'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Image]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.inspect.Config.Image
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: ba301501bbec40e6add5a47d2fd0ee15
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory usage'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemCurrent]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: B
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.MemCurrent
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 5895cddf57fd4b5e8917593cba941491
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory limit'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemLimit]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: B
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.MemLimit
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 640bce04f3fc483fa495ac72208effa7
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory used (%)'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
value_type: FLOAT
|
||||
units: '%'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.MemPerc
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: 9fdd469b0866409ca7889288eb5f229a
|
||||
expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc])>{$DOCKER_MEM_PCT_WARN:"{#DOCKER_CONTAINER_NAME}"}'
|
||||
recovery_mode: RECOVERY_EXPRESSION
|
||||
recovery_expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc])<({$DOCKER_MEM_PCT_WARN:"{#DOCKER_CONTAINER_NAME}"}-2)'
|
||||
name: 'Container {#DOCKER_CONTAINER_NAME} memory usage is at {ITEM.LASTVALUE1}'
|
||||
priority: AVERAGE
|
||||
manual_close: 'YES'
|
||||
-
|
||||
uuid: eb58fb55bc0442319650e32a8ba1faf4
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network in'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOIn]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: b/s
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.NetIOIn
|
||||
-
|
||||
type: CHANGE_PER_SECOND
|
||||
parameters:
|
||||
- ''
|
||||
-
|
||||
type: MULTIPLIER
|
||||
parameters:
|
||||
- '8'
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 6a97e94be7d1432fb11a92072ea9e55f
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network out'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOOut]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: b/s
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.NetIOOut
|
||||
-
|
||||
type: CHANGE_PER_SECOND
|
||||
parameters:
|
||||
- ''
|
||||
-
|
||||
type: MULTIPLIER
|
||||
parameters:
|
||||
- '8'
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 7be56a29b2464c5e96c2f4f2b3e02fba
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: OOMKilled'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},OOMKilled]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.inspect.State.OOMKilled
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: a5ed78ba8acf43a488b3833d14e39381
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Number of processes'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},PIDs]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: '!process(es)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.PIDs
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 1213e0b7fc824442b50ab4ff4cd1047b
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Restarting'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Restarting]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.inspect.State.Restarting
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: 418b35e93f114be986ecdd5a9d259283
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Status'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status]'
|
||||
delay: '0'
|
||||
history: 7d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.inspect.State.Status
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: 45e35825ed184b0290d1bc1ed27e48e4
|
||||
expression: 'find(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],,"regexp","^(running|exited)$")<>1'
|
||||
name: 'Container {#DOCKER_CONTAINER_NAME} is {ITEM.LASTVALUE1}'
|
||||
priority: WARNING
|
||||
manual_close: 'YES'
|
||||
-
|
||||
uuid: ab2c34de197f4ea197e607604c936f34
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Uptime'
|
||||
type: DEPENDENT
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: s
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.stats.Uptime
|
||||
master_item:
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
-
|
||||
uuid: b232a5b3aedd4072a56460dd041579b1
|
||||
name: 'Docker: container {#DOCKER_CONTAINER_NAME}: Info'
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
|
||||
delay: 5m
|
||||
history: '0'
|
||||
trends: '0'
|
||||
value_type: TEXT
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: 57d9a11b38b246539a82bf4ba1a79a98
|
||||
expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime])<{$DOCKER_UPTIME_WARN:"{#DOCKER_CONTAINER_NAME}"} and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],#2)="running" and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status])="running"'
|
||||
name: 'Container {#DOCKER_CONTAINER_NAME} has just restarted'
|
||||
priority: INFO
|
||||
-
|
||||
uuid: ce3cc3148fa24c6097cbf38b47e9e655
|
||||
expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime])<{$DOCKER_UPTIME_WARN:"{#DOCKER_CONTAINER_NAME}"} and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],#2)="exited" and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status])="running"'
|
||||
name: 'Container {#DOCKER_CONTAINER_NAME} has just started'
|
||||
priority: INFO
|
||||
-
|
||||
uuid: ebdea3b26c624714811124fe4681ccec
|
||||
expression: 'max(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime],20m)<{$DOCKER_UPTIME_WARN:"{#DOCKER_CONTAINER_NAME}"} and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime])>0 and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status])="running" and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],#2)="running" and last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],#3)="running"'
|
||||
name: 'Container {#DOCKER_CONTAINER_NAME} seems to restart in a loop'
|
||||
priority: AVERAGE
|
||||
manual_close: 'YES'
|
||||
graph_prototypes:
|
||||
-
|
||||
uuid: 4a9aa378970045399303dcead39c1e53
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: CPU'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
-
|
||||
sortorder: '1'
|
||||
drawtype: GRADIENT_LINE
|
||||
color: F63100
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc]'
|
||||
-
|
||||
uuid: 7cd7cd8fd24d492ab7995a882b7bf9af
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO'
|
||||
graph_items:
|
||||
-
|
||||
sortorder: '1'
|
||||
drawtype: FILLED_REGION
|
||||
color: FFAB91
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIORead]'
|
||||
-
|
||||
sortorder: '2'
|
||||
drawtype: FILLED_REGION
|
||||
color: A5D6A7
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIOWrite]'
|
||||
-
|
||||
uuid: 0fec757ff2f34e4fbab3be8ea455bc5f
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
-
|
||||
sortorder: '1'
|
||||
color: 2774A4
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemCurrent]'
|
||||
-
|
||||
uuid: 948dccce10c54510810a64612933ca89
|
||||
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network'
|
||||
graph_items:
|
||||
-
|
||||
sortorder: '1'
|
||||
drawtype: FILLED_REGION
|
||||
color: B39DDB
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOIn]'
|
||||
-
|
||||
sortorder: '2'
|
||||
drawtype: FILLED_REGION
|
||||
color: 80DEEA
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOOut]'
|
||||
macros:
|
||||
-
|
||||
macro: '{$DOCKER_CPU_PCT_WARN}'
|
||||
value: '90'
|
||||
-
|
||||
macro: '{$DOCKER_MEM_PCT_WARN}'
|
||||
value: '85'
|
||||
-
|
||||
macro: '{$DOCKER_UPTIME_WARN}'
|
||||
value: '300'
|
||||
-
|
||||
macro: '{$DOCKER_WARN_NO_LIVE_RESTORE}'
|
||||
value: '1'
|
||||
graphs:
|
||||
-
|
||||
uuid: 9c9aba9c46e145c7a8acd208edb1d147
|
||||
name: 'Docker: Number of containers'
|
||||
type: STACKED
|
||||
graph_items:
|
||||
-
|
||||
sortorder: '1'
|
||||
color: 1A7C11
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[global,ContainersPaused]'
|
||||
-
|
||||
sortorder: '2'
|
||||
color: F63100
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[global,ContainersRunning]'
|
||||
-
|
||||
sortorder: '3'
|
||||
color: 2774A4
|
||||
item:
|
||||
host: Template_App_Docker
|
||||
key: 'container.docker.check[global,ContainersStopped]'
|
759
zabbix_templates/Template_App_Elasticsearch.yaml
Normal file
759
zabbix_templates/Template_App_Elasticsearch.yaml
Normal file
|
@ -0,0 +1,759 @@
|
|||
zabbix_export:
|
||||
version: '5.4'
|
||||
date: '2021-10-19T12:29:52Z'
|
||||
groups:
|
||||
-
|
||||
uuid: 7df96b18c230490a9a0a9e2307226338
|
||||
name: Templates
|
||||
templates:
|
||||
-
|
||||
uuid: 3a658cb77f26469a8a114b1bcd4734e9
|
||||
template: Template_App_Elasticsearch
|
||||
name: Template_App_Elasticsearch
|
||||
groups:
|
||||
-
|
||||
name: Templates
|
||||
items:
|
||||
-
|
||||
uuid: 1957d2e7393348f9ae73bfc07c1122a3
|
||||
name: 'ES Cluster informations'
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
delay: 3m
|
||||
history: '0'
|
||||
trends: '0'
|
||||
value_type: TEXT
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: fec408ef6d3249a885a3f9842016ccd4
|
||||
name: 'ES: Cluster name'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[cluster_name]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.cluster_name
|
||||
-
|
||||
type: DISCARD_UNCHANGED
|
||||
parameters:
|
||||
- ''
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 286f9eb4d1504704999abd6a98b09a5c
|
||||
name: 'ES: Number of indices'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.count]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!indice(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.count
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
triggers:
|
||||
-
|
||||
uuid: dd7bc1621b994f24917d5beb4c07e17f
|
||||
expression: 'abs(change(/Template_App_Elasticsearch/elasticsearch.cluster[indices.count]))>0'
|
||||
recovery_mode: NONE
|
||||
name: 'Number of indices has changed to {ITEM.LASTVALUE1}'
|
||||
priority: INFO
|
||||
manual_close: 'YES'
|
||||
-
|
||||
uuid: 8b990ab728304cd98d264fdbbe919795
|
||||
name: 'ES: Number of documents'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.docs.count]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!document(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.docs.count
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 4d1b8e4e358749739e3439bf9489b074
|
||||
name: 'ES: Number of deleted documents'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.docs.deleted]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!document(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.docs.deleted
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 0f472265bad44e849866d87de2c50474
|
||||
name: 'ES: Number of primary shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.shards.primaries]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.shards.primaries
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 7118fffe2a864915947ce19570885993
|
||||
name: 'ES: Number of replication shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.shards.replication]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.shards.replication
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 019eb7caa2ff45aa8aad4da89b340a54
|
||||
name: 'ES: Number of shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.shards.total]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.shards.total
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 8f0660a8b80041d987a91986608a43d2
|
||||
name: 'ES: Store size'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[indices.store.size]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: B
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.indices.store.size_in_bytes
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 854e270d75ef4c6fad22ebd553f6438e
|
||||
name: 'ES: Number of data nodes'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.data]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!node(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.nodes.count.data
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 52f72a68d734465b8422fb4e3ad084a7
|
||||
name: 'ES: Number of failed nodes'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.failed]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!node(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $._nodes.failed
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
triggers:
|
||||
-
|
||||
uuid: c188a92cd4444d7f8fe4c635cf35e656
|
||||
expression: 'last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.failed])>0'
|
||||
name: 'ES cluster has {ITEM.LASTVALUE1} failed node(s)'
|
||||
priority: AVERAGE
|
||||
-
|
||||
uuid: 94de965d25ed41cd8d5ef367e9a22497
|
||||
name: 'ES: Available space'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.fs.available_in_bytes]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: B
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.nodes.fs.available_in_bytes
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 376c2cd6bcfa4a21867411af6d84f5d1
|
||||
name: 'ES: Total space'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.fs.total_in_bytes]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: B
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.nodes.fs.total_in_bytes
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 20a0526ae5054c808a95c4cc9b3356eb
|
||||
name: 'ES: Number of master nodes'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.master]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!node(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.nodes.count.master
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 0acd45bc9952407ab582689b0b483149
|
||||
name: 'ES: Number of working nodes'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.successfull]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!node(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $._nodes.successful
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 8ef89bc0bcde44ed89a361a9541f7b85
|
||||
name: 'ES: Number of nodes'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[nodes.total]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!node(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $._nodes.total
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
triggers:
|
||||
-
|
||||
uuid: 82cad93d736248e8b520d25e09cc0fd9
|
||||
expression: 'abs(change(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.total]))>0'
|
||||
recovery_mode: NONE
|
||||
name: 'Number of nodes has changed to {ITEM.LASTVALUE1}'
|
||||
priority: INFO
|
||||
manual_close: 'YES'
|
||||
-
|
||||
uuid: 4782a3f38fb14c16ba2066c3504727da
|
||||
name: 'ES: Cluster status'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.cluster[status]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.status
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 10m
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},cluster]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
triggers:
|
||||
-
|
||||
uuid: b86396f5fcca4dfe825f8ae022ef8edf
|
||||
expression: 'find(/Template_App_Elasticsearch/elasticsearch.cluster[status],,"like","red")=1'
|
||||
name: 'ES cluster in red status'
|
||||
priority: HIGH
|
||||
-
|
||||
uuid: 275c27ab25874666a1cfd8f36df549d0
|
||||
expression: 'find(/Template_App_Elasticsearch/elasticsearch.cluster[status],,"like","green")=0'
|
||||
name: 'ES cluster is in {ITEM.LASTVALUE1} status'
|
||||
priority: WARNING
|
||||
manual_close: 'YES'
|
||||
dependencies:
|
||||
-
|
||||
name: 'ES cluster in red status'
|
||||
expression: 'find(/Template_App_Elasticsearch/elasticsearch.cluster[status],,"like","red")=1'
|
||||
-
|
||||
uuid: c54941e310124d4881bcbb76912a72c9
|
||||
expression: 'nodata(/Template_App_Elasticsearch/elasticsearch.cluster[status],30m)=1'
|
||||
name: 'No data for Elasticsearch cluster monitoring since 10m'
|
||||
priority: WARNING
|
||||
discovery_rules:
|
||||
-
|
||||
uuid: bf3408829ed946a99e0c9640698a2eed
|
||||
name: 'Indices discovery'
|
||||
key: 'elasticsearch.discovery[{$ES_URL},{$ES_USER},{$ES_PASS},indices]'
|
||||
delay: 30m
|
||||
lifetime: 7d
|
||||
item_prototypes:
|
||||
-
|
||||
uuid: 67125ce8f0924ee0a124f06d40715005
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Info'
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
delay: 3m
|
||||
history: '0'
|
||||
trends: '0'
|
||||
value_type: TEXT
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: d457ef885ca442c58fb3c336f2dd8f1d
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Number of active primary shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.index[{#ES_INDEX_NAME},active_primary_shards]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.active_primary_shards
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 465dbc25a40948f392287f784aea1bbe
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Number of active shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.index[{#ES_INDEX_NAME},active_shards]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.active_shards
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 58c0a433f7494045a1aac59586893415
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Number of replicas'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.index[{#ES_INDEX_NAME},number_of_replicas]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.number_of_replicas
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 03c1b057648c4e96937191731206b1ac
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Number of shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.index[{#ES_INDEX_NAME},number_of_shards]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.number_of_shards
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: a13865f166344478ae5e3ea02962b8e2
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Number of relocating shards'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.index[{#ES_INDEX_NAME},relocating_shards]'
|
||||
delay: '0'
|
||||
history: 60d
|
||||
trends: 1095d
|
||||
units: '!shard(s)'
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.relocating_shards
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 1h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: ba3dda72f4144a989e276b0d13c38536
|
||||
name: 'ES: Index: {#ES_INDEX_NAME}: Status'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.index[{#ES_INDEX_NAME},status]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.status
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 10m
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},index,{#ES_INDEX_NAME}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: baeff34841114b31883f0b7e017357a0
|
||||
expression: 'find(/Template_App_Elasticsearch/elasticsearch.index[{#ES_INDEX_NAME},status],,"like","red")=1'
|
||||
name: 'ES index {#ES_INDEX_NAME} is in red status'
|
||||
priority: HIGH
|
||||
manual_close: 'YES'
|
||||
-
|
||||
uuid: 91d45c74b96049158644dc2c4bdc418e
|
||||
expression: 'find(/Template_App_Elasticsearch/elasticsearch.index[{#ES_INDEX_NAME},status],,"like","green")=0'
|
||||
name: 'ES index {#ES_INDEX_NAME} is in {ITEM.LASTVALUE1} status'
|
||||
priority: WARNING
|
||||
manual_close: 'YES'
|
||||
dependencies:
|
||||
-
|
||||
name: 'ES index {#ES_INDEX_NAME} is in red status'
|
||||
expression: 'find(/Template_App_Elasticsearch/elasticsearch.index[{#ES_INDEX_NAME},status],,"like","red")=1'
|
||||
-
|
||||
uuid: 421078e2f66f4fe787a710c10eb45419
|
||||
expression: 'nodata(/Template_App_Elasticsearch/elasticsearch.index[{#ES_INDEX_NAME},status],30m)=1'
|
||||
name: 'No data for Elasticsearch index {#ES_INDEX_NAME} monitoring since 10m'
|
||||
priority: WARNING
|
||||
manual_close: 'YES'
|
||||
dependencies:
|
||||
-
|
||||
name: 'No data for Elasticsearch cluster monitoring since 10m'
|
||||
expression: 'nodata(/Template_App_Elasticsearch/elasticsearch.cluster[status],30m)=1'
|
||||
-
|
||||
uuid: 9912e675734d42e7b3810db51a9c13de
|
||||
name: 'Nodes discovery'
|
||||
key: 'elasticsearch.discovery[{$ES_URL},{$ES_USER},{$ES_PASS},nodes]'
|
||||
delay: 2h
|
||||
lifetime: 7d
|
||||
item_prototypes:
|
||||
-
|
||||
uuid: 70e411ebd3de4f79936ec65ad4b3e41a
|
||||
name: 'ES: Node {#ES_NODE_NAME} ({#ES_NODE_ID}): Info'
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},node,{#ES_NODE_ID}]'
|
||||
delay: 5m
|
||||
history: '0'
|
||||
trends: '0'
|
||||
value_type: TEXT
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
-
|
||||
uuid: 0b7eed934ccf4e90b95daced49c7ccde
|
||||
name: 'ES: Node {#ES_NODE_NAME} ({#ES_NODE_ID}): Uptime'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.node[{#ES_NODE_ID},jvm.start_time_in_millis]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: 1095d
|
||||
units: ms
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.jvm.start_time_in_millis
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},node,{#ES_NODE_ID}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: e2b5fac004e240e1b381a0f3ce17db4f
|
||||
expression: 'last(/Template_App_Elasticsearch/elasticsearch.node[{#ES_NODE_ID},jvm.start_time_in_millis])<600000'
|
||||
name: 'ES restarted recently'
|
||||
priority: INFO
|
||||
manual_close: 'YES'
|
||||
-
|
||||
uuid: c335b6ee20d8497393125f9b1a4f7157
|
||||
name: 'ES: Node {#ES_NODE_NAME} ({#ES_NODE_ID}): ES version'
|
||||
type: DEPENDENT
|
||||
key: 'elasticsearch.node[{#ES_NODE_ID},version]'
|
||||
delay: '0'
|
||||
history: 30d
|
||||
trends: '0'
|
||||
value_type: CHAR
|
||||
preprocessing:
|
||||
-
|
||||
type: JSONPATH
|
||||
parameters:
|
||||
- $.version
|
||||
-
|
||||
type: DISCARD_UNCHANGED_HEARTBEAT
|
||||
parameters:
|
||||
- 6h
|
||||
master_item:
|
||||
key: 'elasticsearch.check[{$ES_URL},{$ES_USER},{$ES_PASS},node,{#ES_NODE_ID}]'
|
||||
tags:
|
||||
-
|
||||
tag: Application
|
||||
value: Elasticsearch
|
||||
trigger_prototypes:
|
||||
-
|
||||
uuid: 15b5d7f22ca2422f9f79f6ee0196d38e
|
||||
expression: 'last(/Template_App_Elasticsearch/elasticsearch.node[{#ES_NODE_ID},version],#1)<>last(/Template_App_Elasticsearch/elasticsearch.node[{#ES_NODE_ID},version],#2)'
|
||||
recovery_mode: NONE
|
||||
name: 'ES version changed to {ITEM.LASTVALUE1} on node {#ES_NODE_NAME} ({#ES_NODE_ID})'
|
||||
priority: INFO
|
||||
manual_close: 'YES'
|
||||
macros:
|
||||
-
|
||||
macro: '{$ES_PASS}'
|
||||
-
|
||||
macro: '{$ES_SPACE_PCT_CRIT}'
|
||||
value: '88'
|
||||
-
|
||||
macro: '{$ES_SPACE_PCT_WARN}'
|
||||
value: '78'
|
||||
-
|
||||
macro: '{$ES_URL}'
|
||||
value: 'http://localhost:9200'
|
||||
-
|
||||
macro: '{$ES_USER}'
|
||||
triggers:
|
||||
-
|
||||
uuid: e5ff617704b047e2814469075a1a9e38
|
||||
expression: '(100*last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.fs.available_in_bytes])/last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.fs.total_in_bytes]))<(100-{$ES_SPACE_PCT_WARN})'
|
||||
name: 'Low free disk space'
|
||||
priority: WARNING
|
||||
dependencies:
|
||||
-
|
||||
name: 'Very low free disk space'
|
||||
expression: '(100*last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.fs.available_in_bytes])/last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.fs.total_in_bytes]))<(100-{$ES_SPACE_PCT_CRIT})'
|
||||
-
|
||||
uuid: c6dbde1d2a844e338bb05dee6f59b114
|
||||
expression: '(100*last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.fs.available_in_bytes])/last(/Template_App_Elasticsearch/elasticsearch.cluster[nodes.fs.total_in_bytes]))<(100-{$ES_SPACE_PCT_CRIT})'
|
||||
name: 'Very low free disk space'
|
||||
priority: HIGH
|
||||
graphs:
|
||||
-
|
||||
uuid: 83738984fe6f4ab1b5a71e150c248ae4
|
||||
name: 'ES: Storage size'
|
||||
graph_items:
|
||||
-
|
||||
drawtype: GRADIENT_LINE
|
||||
color: 1A7C11
|
||||
item:
|
||||
host: Template_App_Elasticsearch
|
||||
key: 'elasticsearch.cluster[indices.store.size]'
|
138
zabbix_templates/Template_App_GlusterFS.xml
Normal file
138
zabbix_templates/Template_App_GlusterFS.xml
Normal file
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-06-19T12:08:07Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_GlusterFS</template>
|
||||
<name>Template_App_GlusterFS</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Gluster</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<items>
|
||||
<item>
|
||||
<name>GlusterFS: memory used by gluster processes</name>
|
||||
<key>proc.mem[glusterfs]</key>
|
||||
<delay>5m</delay>
|
||||
<trends>730d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Gluster</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>GlusterFS: number of processes</name>
|
||||
<key>proc.num[glusterfs]</key>
|
||||
<delay>5m</delay>
|
||||
<trends>730d</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Gluster</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{last()}<1</expression>
|
||||
<name>GlusterFS: No gluster process runing</name>
|
||||
<priority>HIGH</priority>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
</items>
|
||||
<discovery_rules>
|
||||
<discovery_rule>
|
||||
<name>GlusterFS: peer discovery</name>
|
||||
<key>gluster.discovery[peers]</key>
|
||||
<delay>2h</delay>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>GlusterFS peer: {#GLUSTER_PEER_UUID} ({#GLUSTER_PEER_HOST}) status</name>
|
||||
<key>gluster.peer.status[{#GLUSTER_PEER_UUID}]</key>
|
||||
<delay>633s</delay>
|
||||
<trends>0</trends>
|
||||
<value_type>CHAR</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Gluster</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{str(Connected)}=0</expression>
|
||||
<name>GlusterFS peer {#GLUSTER_PEER_HOST} disconnected</name>
|
||||
<priority>HIGH</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<request_method>POST</request_method>
|
||||
</discovery_rule>
|
||||
<discovery_rule>
|
||||
<name>GlusterFS: Volume discovery</name>
|
||||
<key>gluster.discovery[volumes]</key>
|
||||
<delay>2h</delay>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>GlusterFS {#GLUSTER_VOL_NAME} status</name>
|
||||
<key>gluster.volume.status[{#GLUSTER_VOL_NAME},{#GLUSTER_VOL_BRICKS}]</key>
|
||||
<delay>614s</delay>
|
||||
<trends>0</trends>
|
||||
<value_type>CHAR</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Gluster</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>Storage</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{str(OK)}=0</expression>
|
||||
<name>GlusterFS: {#GLUSTER_VOL_NAME} failure detected</name>
|
||||
<priority>HIGH</priority>
|
||||
</trigger_prototype>
|
||||
<trigger_prototype>
|
||||
<expression>{nodata(2460)}=1</expression>
|
||||
<name>GlusterFS: {#GLUSTER_VOL_NAME} not sending health info</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<request_method>POST</request_method>
|
||||
</discovery_rule>
|
||||
</discovery_rules>
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
97
zabbix_templates/Template_App_HSQL.xml
Normal file
97
zabbix_templates/Template_App_HSQL.xml
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-06-19T12:08:22Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_HSQL</template>
|
||||
<name>Template_App_HSQL</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>HSQL</name>
|
||||
</application>
|
||||
</applications>
|
||||
<items>
|
||||
<item>
|
||||
<name>HSQL TCP Service</name>
|
||||
<key>net.tcp.listen[{$HSQL_PORT}]</key>
|
||||
<delay>6m</delay>
|
||||
<history>30d</history>
|
||||
<trends>0</trends>
|
||||
<applications>
|
||||
<application>
|
||||
<name>HSQL</name>
|
||||
</application>
|
||||
</applications>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{last()}<>1</expression>
|
||||
<name>HSQL port {$HSQL_PORT} is not listening</name>
|
||||
<priority>WARNING</priority>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<name>No HSQL Service running</name>
|
||||
<expression>{Template_App_HSQL:proc.num[manta,hyperfile,,HFCS-Serveur].last()}<1</expression>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
<item>
|
||||
<name>HSQL Server Processes</name>
|
||||
<key>proc.num[manta,hyperfile,,HFCS-Serveur]</key>
|
||||
<delay>5m</delay>
|
||||
<history>30d</history>
|
||||
<units>!process</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>HSQL</name>
|
||||
</application>
|
||||
</applications>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{last()}<1</expression>
|
||||
<name>No HSQL Service running</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
<item>
|
||||
<name>HSQL MantaManager Processes</name>
|
||||
<key>proc.num[mantamanager,root,,]</key>
|
||||
<delay>5m</delay>
|
||||
<history>30d</history>
|
||||
<units>!process</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>HSQL</name>
|
||||
</application>
|
||||
</applications>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{last()}<1</expression>
|
||||
<name>No HSQL Manager Service running</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
</items>
|
||||
<macros>
|
||||
<macro>
|
||||
<macro>{$HSQL_PORT}</macro>
|
||||
<value>4900</value>
|
||||
</macro>
|
||||
</macros>
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
363
zabbix_templates/Template_App_Multipath.xml
Normal file
363
zabbix_templates/Template_App_Multipath.xml
Normal file
|
@ -0,0 +1,363 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-06-19T12:08:45Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_Multipath</template>
|
||||
<name>Template_App_Multipath</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<discovery_rules>
|
||||
<discovery_rule>
|
||||
<name>Multipath devices discovery</name>
|
||||
<key>vfs.mpath.discovery[mpath]</key>
|
||||
<delay>20m</delay>
|
||||
<lifetime>2d</lifetime>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>Multipath info for {#MPATH_DEV}</name>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
<delay>5m</delay>
|
||||
<history>0</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Status for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},dm_st]</key>
|
||||
<delay>0</delay>
|
||||
<history>30d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.dm_st</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{str(active)}<>1</expression>
|
||||
<name>mpath device {#MPATH_DEV} is in {ITEM.LASTVALUE1} state</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger_prototype>
|
||||
<trigger_prototype>
|
||||
<expression>{nodata(1800)}=1</expression>
|
||||
<name>No more monitoring data for {#MPATH_DEV}</name>
|
||||
<priority>AVERAGE</priority>
|
||||
<manual_close>YES</manual_close>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Errors for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},errors]</key>
|
||||
<delay>0</delay>
|
||||
<history>30d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.errors</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Number device failures for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},failures]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!errors</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.failures</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{last()}>0</expression>
|
||||
<name>Failures on mpath device {#MPATH_DEV}</name>
|
||||
<priority>AVERAGE</priority>
|
||||
<manual_close>YES</manual_close>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Features for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},features]</key>
|
||||
<delay>0</delay>
|
||||
<history>30d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.features</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{change()}<>0</expression>
|
||||
<recovery_mode>NONE</recovery_mode>
|
||||
<name>Features for mpath {#MPATH_DEV} changed</name>
|
||||
<priority>INFO</priority>
|
||||
<manual_close>YES</manual_close>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Number of active paths for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},paths_num_active]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!path(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.paths_num_active</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Number of inactive paths for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},paths_num_inactive]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!path(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.paths_num_inactive</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Number of paths having issues for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},paths_num_ko]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!path(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.paths_num_ko</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Number of operational paths for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},paths_num_ok]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!path(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.paths_num_ok</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Total number of paths for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},paths_num_total]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!path(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.paths_num_total</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Paths with issues for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},paths_with_issue]</key>
|
||||
<delay>0</delay>
|
||||
<history>30d</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.paths_with_issue</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Number path failures for {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},path_failures]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>!path(s)</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.path_failures</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>Multipath: Size of the device {#MPATH_DEV}</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>vfs.mpath[{#MPATH_DEV},size]</key>
|
||||
<delay>0</delay>
|
||||
<history>60d</history>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>mpath</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.size</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>vfs.mpath.info[{#MPATH_DEV}]</key>
|
||||
</master_item>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{change()}<>0</expression>
|
||||
<recovery_mode>NONE</recovery_mode>
|
||||
<name>Size of mpath {#MPATH_DEV} changed</name>
|
||||
<priority>INFO</priority>
|
||||
<manual_close>YES</manual_close>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{Template_App_Multipath:vfs.mpath[{#MPATH_DEV},path_failures].last()}>0 or {Template_App_Multipath:vfs.mpath[{#MPATH_DEV},paths_num_ko].last()}>0 or {Template_App_Multipath:vfs.mpath[{#MPATH_DEV},failures].last()}>0 or {Template_App_Multipath:vfs.mpath[{#MPATH_DEV},paths_num_ok].last()}<>{Template_App_Multipath:vfs.mpath[{#MPATH_DEV},paths_num_active].last()} or {Template_App_Multipath:vfs.mpath[{#MPATH_DEV},paths_with_issue].strlen()}<>0</expression>
|
||||
<name>Issues detected on {#MPATH_DEV} ({ITEM.VALUE6})</name>
|
||||
<priority>WARNING</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</discovery_rule>
|
||||
</discovery_rules>
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
1195
zabbix_templates/Template_App_MySQL.xml
Normal file
1195
zabbix_templates/Template_App_MySQL.xml
Normal file
File diff suppressed because it is too large
Load Diff
78
zabbix_templates/Template_App_MySQL_Legacy.xml
Normal file
78
zabbix_templates/Template_App_MySQL_Legacy.xml
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-06-19T12:09:19Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Modèles</name>
|
||||
</group>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_MySQL_legacy</template>
|
||||
<name>Template_App_MySQL_legacy</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Modèles</name>
|
||||
</group>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<items>
|
||||
<item>
|
||||
<name>MySQL queries per second</name>
|
||||
<key>mysql.qps</key>
|
||||
<delay>5m</delay>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>qps</units>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>MySQL number of slow queries</name>
|
||||
<key>mysql.slowqueries</key>
|
||||
<delay>5m</delay>
|
||||
<trends>1095d</trends>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>MySQL number of threads</name>
|
||||
<key>mysql.threads</key>
|
||||
<delay>5m</delay>
|
||||
<trends>1095d</trends>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>MySQL uptime</name>
|
||||
<key>mysql.uptime</key>
|
||||
<delay>5m</delay>
|
||||
<trends>1095d</trends>
|
||||
<status>DISABLED</status>
|
||||
<units>uptime</units>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>MySQL is alive</name>
|
||||
<key>mysql[ping]</key>
|
||||
<delay>5m</delay>
|
||||
<trends>1095d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>MySQL version</name>
|
||||
<key>version[mysql]</key>
|
||||
<delay>2h</delay>
|
||||
<trends>0</trends>
|
||||
<status>DISABLED</status>
|
||||
<value_type>CHAR</value_type>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
</items>
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
991
zabbix_templates/Template_App_PMG.xml
Normal file
991
zabbix_templates/Template_App_PMG.xml
Normal file
|
@ -0,0 +1,991 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zabbix_export>
|
||||
<version>5.0</version>
|
||||
<date>2021-06-19T12:09:38Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Template_App_PMG</template>
|
||||
<name>Template_App_PMG</name>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>pmg</name>
|
||||
</application>
|
||||
</applications>
|
||||
<items>
|
||||
<item>
|
||||
<name>PMG: Global stats</name>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
<delay>15m</delay>
|
||||
<history>1h</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Inbound email trafic</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,bytes_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bytes_in</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Outbound email trafic</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,bytes_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bytes_out</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Inbound emails</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,count_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.count_in</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Outbound email</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,count_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.count_out</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Pregreet rejections</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,pregreet]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.pregreet</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Inbound average processing time</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,ptime_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>s</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.ptime_in</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Outbound average processing time</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,ptime_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>s</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.ptime_out</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Emails in the active queue</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,queue_active]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.queue_active</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Emails in the deferred queue</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,queue_deferred]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.queue_deferred</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Emails in the hold queue</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,queue_hold]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.queue_hold</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{last()}>0</expression>
|
||||
<name>Quarantined emails</name>
|
||||
<priority>WARNING</priority>
|
||||
<description>Check hold queue with the mailq command then either release with postsuper -H <ID> or drop with postsuper -d <ID></description>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: RBL rejections</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,rbl]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.rbl</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Inbound spams</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,spam_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.spam_in</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Outbound spam</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,spam_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.spam_out</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{max(1h)}>0</expression>
|
||||
<name>PMG: Outbound spam detected</name>
|
||||
<priority>WARNING</priority>
|
||||
<manual_close>YES</manual_close>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Inbound viruses</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,virus_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.virus_in</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item>
|
||||
<item>
|
||||
<name>PMG: Outbound viruses</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pmg.check[global,virus_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.virus_out</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
<triggers>
|
||||
<trigger>
|
||||
<expression>{max(1h)}>0</expression>
|
||||
<name>PMG: Outbound viruses detected</name>
|
||||
<priority>AVERAGE</priority>
|
||||
<manual_close>YES</manual_close>
|
||||
</trigger>
|
||||
</triggers>
|
||||
</item>
|
||||
</items>
|
||||
<discovery_rules>
|
||||
<discovery_rule>
|
||||
<name>Domains discovery</name>
|
||||
<key>pmg.discovery[domains]</key>
|
||||
<delay>7200</delay>
|
||||
<item_prototypes>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN} Info</name>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
<delay>15m</delay>
|
||||
<history>0</history>
|
||||
<trends>0</trends>
|
||||
<value_type>TEXT</value_type>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
<application>
|
||||
<name>pmg</name>
|
||||
</application>
|
||||
</applications>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Inbound trafic</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},bytes_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bytes_in</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Outbound trafic</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},bytes_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>B</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.bytes_out</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Inbound emails</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},count_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.count_in</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Outbound emails</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},count_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.count_out</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain {#PMG_RELAY_DOMAIN}: Inbound average processing time</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},ptime_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>s</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.ptime_in</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Outbound average processing time</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},ptime_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<value_type>FLOAT</value_type>
|
||||
<units>s</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.ptime_out</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Inbound spam</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},spam_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.spam_in</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Outbound spam</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},spam_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.spam_out</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{max(1800)}>1</expression>
|
||||
<name>PMG: {#PMG_RELAY_DOMAIN}: Outbound spam detected</name>
|
||||
<priority>AVERAGE</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Inbound viruses</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},virus_in]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.virus_in</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
</item_prototype>
|
||||
<item_prototype>
|
||||
<name>PMG Domain: {#PMG_RELAY_DOMAIN}: Outbound viruses</name>
|
||||
<type>DEPENDENT</type>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},virus_out]</key>
|
||||
<delay>0</delay>
|
||||
<trends>1825d</trends>
|
||||
<units>mails/h</units>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Email</name>
|
||||
</application>
|
||||
</applications>
|
||||
<preprocessing>
|
||||
<step>
|
||||
<type>JSONPATH</type>
|
||||
<params>$.virus_out</params>
|
||||
</step>
|
||||
<step>
|
||||
<type>MULTIPLIER</type>
|
||||
<params>4</params>
|
||||
</step>
|
||||
</preprocessing>
|
||||
<master_item>
|
||||
<key>pmg.check.all[{$PMG_FREQ},{$PMG_SPAM_THRES},domain,{#PMG_RELAY_DOMAIN}]</key>
|
||||
</master_item>
|
||||
<request_method>POST</request_method>
|
||||
<trigger_prototypes>
|
||||
<trigger_prototype>
|
||||
<expression>{max(1800)}>1</expression>
|
||||
<name>PMG: {#PMG_RELAY_DOMAIN}: Outbound viruses detected</name>
|
||||
<priority>HIGH</priority>
|
||||
</trigger_prototype>
|
||||
</trigger_prototypes>
|
||||
</item_prototype>
|
||||
</item_prototypes>
|
||||
<graph_prototypes>
|
||||
<graph_prototype>
|
||||
<name>PMG: Domain {#PMG_RELAY_DOMAIN}: Email flows</name>
|
||||
<type>STACKED</type>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<color>DD0000</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},virus_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<color>FF33FF</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},spam_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<color>00DD00</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},count_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>3</sortorder>
|
||||
<color>0000DD</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},spam_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>4</sortorder>
|
||||
<color>000000</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},virus_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>5</sortorder>
|
||||
<color>00EEEE</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},count_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph_prototype>
|
||||
<graph_prototype>
|
||||
<name>PMG: Domain {#PMG_RELAY_DOMAIN}: Trafic and processing time</name>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<drawtype>GRADIENT_LINE</drawtype>
|
||||
<color>00DD00</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},bytes_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<drawtype>GRADIENT_LINE</drawtype>
|
||||
<color>FF9999</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},bytes_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<drawtype>BOLD_LINE</drawtype>
|
||||
<color>3333FF</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},ptime_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>3</sortorder>
|
||||
<drawtype>BOLD_LINE</drawtype>
|
||||
<color>DD0000</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pve.check[domain,{#PMG_RELAY_DOMAIN},ptime_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph_prototype>
|
||||
</graph_prototypes>
|
||||
<request_method>POST</request_method>
|
||||
</discovery_rule>
|
||||
</discovery_rules>
|
||||
<macros>
|
||||
<macro>
|
||||
<macro>{$PMG_FREQ}</macro>
|
||||
<value>900</value>
|
||||
</macro>
|
||||
<macro>
|
||||
<macro>{$PMG_SPAM_THRES}</macro>
|
||||
<value>5</value>
|
||||
</macro>
|
||||
</macros>
|
||||
</template>
|
||||
</templates>
|
||||
<graphs>
|
||||
<graph>
|
||||
<name>PMG: Global email flows</name>
|
||||
<type>STACKED</type>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<color>FF6F00</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,virus_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<color>CE93D8</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,spam_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<color>6A1B9A</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,count_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>3</sortorder>
|
||||
<color>1A7C11</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,count_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>4</sortorder>
|
||||
<color>80FF00</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,spam_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>5</sortorder>
|
||||
<color>B71C1C</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,virus_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>6</sortorder>
|
||||
<color>0040FF</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,rbl]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>7</sortorder>
|
||||
<color>90A4AE</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,pregreet]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph>
|
||||
<graph>
|
||||
<name>PMG: Global email trafic and processing time</name>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<drawtype>GRADIENT_LINE</drawtype>
|
||||
<color>00DD00</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,bytes_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<drawtype>GRADIENT_LINE</drawtype>
|
||||
<color>FF9999</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,bytes_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<drawtype>BOLD_LINE</drawtype>
|
||||
<color>0000DD</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,ptime_in]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>3</sortorder>
|
||||
<drawtype>BOLD_LINE</drawtype>
|
||||
<color>DD0000</color>
|
||||
<yaxisside>RIGHT</yaxisside>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,ptime_out]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph>
|
||||
<graph>
|
||||
<name>PMG: Global queues</name>
|
||||
<type>STACKED</type>
|
||||
<graph_items>
|
||||
<graph_item>
|
||||
<color>81C784</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,queue_active]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>1</sortorder>
|
||||
<color>8E24AA</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,queue_hold]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
<graph_item>
|
||||
<sortorder>2</sortorder>
|
||||
<color>EC407A</color>
|
||||
<item>
|
||||
<host>Template_App_PMG</host>
|
||||
<key>pmg.check[global,queue_deferred]</key>
|
||||
</item>
|
||||
</graph_item>
|
||||
</graph_items>
|
||||
</graph>
|
||||
</graphs>
|
||||
</zabbix_export>
|
2054
zabbix_templates/Template_App_PVE_Cluster.xml
Normal file
2054
zabbix_templates/Template_App_PVE_Cluster.xml
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user