Zabbix Skripte Maintenance Host oder Gruppe
Aus znilwiki
Ab Zabbix 6.0 kann man einen API-Key statt Benutzernamen und Passwort nutzen,
ab Zabbix 6.4 muss man das sogar. Das Skript muss noch auf API-Key Nutzung umgebaut werden!
Für das UI-Skript wurde das schon gemacht: Host per Popup-Skript aus der Zabbix-Server Weboberfläche in Wartung setzen
Ich habe unten eine neue Version als Test bereit gestellt, die ist aber noch nicht getestet
Die beiden Skripte nutze ich als Alertscripts und als Externalscripts direkt auf dem Zabbix Server.
Das Skript für die Hosts ist nahezu 1:1 das von
https://www.zabbix.org/wiki/Perl_script_to_add/remove_Maintenance
Ich habe nur den Fehler bei der Abfrage beseitigt (es wurden immer alle Hosts zurückgegeben, nicht nur der gewünschte).
Außerdem ignoriert es bei https Fehler mit selbst-signierten Zertifikaten.
Das Skript für die Gruppen ist das gleiche Skript nur angepasst an die Gruppen.
Hosts
nano zabbix_main_host.pl
Bis Zabbix 6.0
#!/usr/bin/perl
use strict;
use Getopt::Std;
use vars qw/ %opt /;
my $url = "http://localhost/api_jsonrpc.php"; # change <zabbix server> to your zabbix server
my $apiuser="username"; # API User's Username
my $apipassword="password"; # API User's password
my $maintenanceid;
#############
# Begin main
#
init();
my $hostname = $opt{s};
my $duration = $opt{d} || 10800;
my $maintname = $opt{n};
# Authenticate against Zabbix for API Maintenance addition
my $auth = newrequest($url, $apiuser, $apipassword);
my $hostid = gethostid($hostname);
if($opt{r}){
print "Removing maintenance for host $hostname\n";
getmaintid($hostid,$maintname);
exit(0);
}else{
print "Adding maintenance for host $hostname\n";
addmaint($hostid,$duration,$maintname);
}
exit(0);
#########################
# Get command line input
#
sub init(){
my $opt_string = 'hrs:d:n:';
getopts( "$opt_string", \%opt ) or usage();
usage() if $opt{h};
usage() if !$opt{s};
usage() if !$opt{n};
}
#####################
# Print script usage
#
sub usage(){
print STDERR << "EOF";
usage: $0 [-hr] -s hostname [-d duration] -n name
-h : This (help) message
-r : Remove maintenance for specified host
-s hostname : Hostname in Zabbix
-d : Duration of maintenance in seconds. Leave blank to use default.
300 = 5 minutes
1800 = 30 minutes
3600 = 1 hour
10800 = 3 hour (default)
-n name : unique identifier
-s and -n are required
example: $0 -s hostname -d 3600 -n backup
example: $0 -s hostname -r -n backup
EOF
exit;
}
#############################################
# Zabbix API requests require authentication
#
sub newrequest {
my ($url, $user, $password) = @_;
my $authenticate = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"params": {
"password": "$password",
"user": "$user"
},
"jsonrpc": "2.0",
"method": "user.login",
"id": 0
}' $url | grep result | head -n 1 | cut -d '"' -f 8);
my $auth = `$authenticate`;
chomp($auth);
return $auth
}
###################################################
# Subroutine to query Zabbix to get host id
#
sub gethostid{
my $hostname = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"params": {
"filter": {
"name": "$hostname"
}
},
"jsonrpc": "2.0",
"method": "host.get",
"auth": "$auth",
"id": 2 }' $url);
my $res = `$process`;
chomp($res);
# print "$res \n\n";
my @output = split(/,/,$res);
my $x=0;
foreach(@output){
if (($output[$x] =~ m/\"host\"/)&&($output[$x] =~ m/$hostname/)){
$output[$x-2] =~ s/\[\{//g;
$output[$x-2] =~ s/"//g;
$output[$x-2] =~ s/hostid://g;
$output[$x-2] =~ s/result://g;
$output[$x-2] =~ s/\{//g;
$hostid = $output[$x-2];
}
$x++;
}
if(!$hostid){
print "WARNING - $hostname not found in maintenance for Zabbix.\n";
exit(1);
}
print "Host ID: ".$hostid."\n";
return $hostid
}
###################################################
# Subroutine to query Zabbix to get maintenance id
#
sub getmaintid{
my $hostid = shift;
my $maintname = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"params": {
"output": "extend",
"selectHosts": "refer",
"selectGroups": "refer",
"hostids": "$hostid"
},
"jsonrpc": "2.0",
"method": "maintenance.get",
"auth": "$auth",
"id": 2 }' $url);
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
my $x=0;
foreach(@output){
if (($output[$x] =~ m/\"name\"/)&&($output[$x] =~ m/ID $maintname/)){
$output[$x-1] =~ s/\[\{//g;
$output[$x-1] =~ s/"//g;
$output[$x-1] =~ s/maintenanceid://g;
$output[$x-1] =~ s/result://g;
$output[$x-1] =~ s/\{//g;
$maintenanceid = $output[$x-1];
remmaint($maintenanceid);
}
$x++;
}
if(!$maintenanceid){
print "WARNING - $hostname not found in maintenance for Zabbix.\n";
exit(1);
}
}
#################################################
# Subroutine to add maintenance window to Zabbix
#
sub addmaint{
$hostid = shift;
$duration = shift;
$maintname = shift;
my $start = time();
my $end = ($start + $duration);
# my $auth = newrequest($url, $apiuser, $apipassword);
my $process = 'curl -k -s -i -X POST -H \'Content-Type: application/json-rpc\' -d "{
\"jsonrpc\":\"2.0\",
\"method\":\"maintenance.create\",
\"params\":[{
\"groupids\":[],
\"hostids\":[\"'.$hostid.'\"],
\"name\":\"000_Manually Maintenance Mode with ID '.$maintname.' - '.$start.'\",
\"maintenance_type\":\"0\",
\"description\":\"000_Manually Maintenance Mode for '.$hostname.' set by Linux-Admin\",
\"active_since\":\"'.$start.'\",
\"active_till\":\"'.$end.'\",
\"timeperiods\": [{
\"timeperiod_type\": 0,
\"start_date\": \"'.$start.'\",
\"period\": '.$duration.'}]
}],
\"auth\":\"'.$auth.'\",
\"id\":3}" '.$url;
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
foreach(@output){
if ($_ =~ m/\"error/){
print "$_\n";
exit(1);
}
print "$_\n" if ($_ =~ m/\"result/);
}
}
#################################################
# Subroutine to remove maintenance window from Zabbix
#
sub remmaint{
$maintenanceid = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"jsonrpc":"2.0",
"method":"maintenance.delete",
"params":["$maintenanceid"],
"auth":"$auth",
"id":2}' $url);
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
foreach(@output){
print "$_\n" if ($_ =~ m/\"error/);
print "$_\n" if ($_ =~ m/\"result/);
}
}
Ab Zabbix 6.2 (ungetestet)
#!/usr/bin/perl
use strict;
use Getopt::Std;
use vars qw/ %opt /;
my $url = "http://localhost/api_jsonrpc.php"; # change <zabbix server> to your zabbix server
my $apiuser="username"; # API User's Username
my $apitoken="Bearer bla123bla";
my $maintenanceid;
#############
# Begin main
#
init();
my $hostname = $opt{s};
my $duration = $opt{d} || 10800;
my $maintname = $opt{n};
# Authenticate against Zabbix for API Maintenance addition
# my $auth = newrequest($url, $apiuser, $apipassword);
my $hostid = gethostid($hostname);
if($opt{r}){
print "Removing maintenance for host $hostname\n";
getmaintid($hostid,$maintname);
exit(0);
}else{
print "Adding maintenance for host $hostname\n";
addmaint($hostid,$duration,$maintname);
}
exit(0);
#########################
# Get command line input
#
sub init(){
my $opt_string = 'hrs:d:n:';
getopts( "$opt_string", \%opt ) or usage();
usage() if $opt{h};
usage() if !$opt{s};
usage() if !$opt{n};
}
#####################
# Print script usage
#
sub usage(){
print STDERR << "EOF";
usage: $0 [-hr] -s hostname [-d duration] -n name
-h : This (help) message
-r : Remove maintenance for specified host
-s hostname : Hostname in Zabbix
-d : Duration of maintenance in seconds. Leave blank to use default.
300 = 5 minutes
1800 = 30 minutes
3600 = 1 hour
10800 = 3 hour (default)
-n name : unique identifier
-s and -n are required
example: $0 -s hostname -d 3600 -n backup
example: $0 -s hostname -r -n backup
EOF
exit;
}
#############################################
# Zabbix API requests require authentication
#
#sub newrequest {
# my ($url, $user, $password) = @_;
#
# my $authenticate = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
# "params": {
# "password": "$password",
# "user": "$user"
# },
# "jsonrpc": "2.0",
# "method": "user.login",
# "id": 0
# }' $url | grep result | head -n 1 | cut -d '"' -f 8);
# my $auth = `$authenticate`;
# chomp($auth);
# return $auth
#}
###################################################
# Subroutine to query Zabbix to get host id
#
sub gethostid{
my $hostname = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -H 'Authorization: $apitoken' -d '{
"params": {
"filter": {
"name": "$hostname"
}
},
"jsonrpc": "2.0",
"method": "host.get",
"auth": "$auth",
"id": 2 }' $url);
my $res = `$process`;
chomp($res);
# print "$res \n\n";
my @output = split(/,/,$res);
my $x=0;
foreach(@output){
if (($output[$x] =~ m/\"host\"/)&&($output[$x] =~ m/$hostname/)){
$output[$x-2] =~ s/\[\{//g;
$output[$x-2] =~ s/"//g;
$output[$x-2] =~ s/hostid://g;
$output[$x-2] =~ s/result://g;
$output[$x-2] =~ s/\{//g;
$hostid = $output[$x-2];
}
$x++;
}
if(!$hostid){
print "WARNING - $hostname not found in maintenance for Zabbix.\n";
exit(1);
}
print "Host ID: ".$hostid."\n";
return $hostid
}
###################################################
# Subroutine to query Zabbix to get maintenance id
#
sub getmaintid{
my $hostid = shift;
my $maintname = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -H 'Authorization: $apitoken' -d '{
"params": {
"output": "extend",
"selectHosts": "refer",
"selectGroups": "refer",
"hostids": "$hostid"
},
"jsonrpc": "2.0",
"method": "maintenance.get",
"auth": "$auth",
"id": 2 }' $url);
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
my $x=0;
foreach(@output){
if (($output[$x] =~ m/\"name\"/)&&($output[$x] =~ m/ID $maintname/)){
$output[$x-1] =~ s/\[\{//g;
$output[$x-1] =~ s/"//g;
$output[$x-1] =~ s/maintenanceid://g;
$output[$x-1] =~ s/result://g;
$output[$x-1] =~ s/\{//g;
$maintenanceid = $output[$x-1];
remmaint($maintenanceid);
}
$x++;
}
if(!$maintenanceid){
print "WARNING - $hostname not found in maintenance for Zabbix.\n";
exit(1);
}
}
#################################################
# Subroutine to add maintenance window to Zabbix
#
sub addmaint{
$hostid = shift;
$duration = shift;
$maintname = shift;
my $start = time();
my $end = ($start + $duration);
# my $auth = newrequest($url, $apiuser, $apipassword);
my $process = 'curl -k -s -i -X POST -H \'Content-Type: application/json-rpc\' -H 'Authorization: $apitoken' -d "{
\"jsonrpc\":\"2.0\",
\"method\":\"maintenance.create\",
\"params\":[{
\"groupids\":[],
\"hostids\":[\"'.$hostid.'\"],
\"name\":\"000_Manually Maintenance Mode with ID '.$maintname.' - '.$start.'\",
\"maintenance_type\":\"0\",
\"description\":\"000_Manually Maintenance Mode for '.$hostname.' set by Linux-Admin\",
\"active_since\":\"'.$start.'\",
\"active_till\":\"'.$end.'\",
\"timeperiods\": [{
\"timeperiod_type\": 0,
\"start_date\": \"'.$start.'\",
\"period\": '.$duration.'}]
}],
\"auth\":\"'.$auth.'\",
\"id\":3}" '.$url;
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
foreach(@output){
if ($_ =~ m/\"error/){
print "$_\n";
exit(1);
}
print "$_\n" if ($_ =~ m/\"result/);
}
}
#################################################
# Subroutine to remove maintenance window from Zabbix
#
sub remmaint{
$maintenanceid = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -H 'Authorization: $apitoken' -d '{
"jsonrpc":"2.0",
"method":"maintenance.delete",
"params":["$maintenanceid"],
"auth":"$auth",
"id":2}' $url);
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
foreach(@output){
print "$_\n" if ($_ =~ m/\"error/);
print "$_\n" if ($_ =~ m/\"result/);
}
}
Einbindung in Zabbix Oberfläche
Unter
Administration => Scripts
habe ich folgende Skripte angelegt:
Im Detail:
Dadurch habe ich an jedem Host folgendes Menu (z.B. in der Problems-Ansicht):
So kann ich - falls ich mal wieder Updates einspiele und vergessen habe den Host in den Maintenance-Modus zu setzen - diese eben schnell nachholen.
Man kann das Skript auch natürlich auch aus anderen Programmen aufrufen - z.B. um aus dem Ticketsystem bei genehmigten Change die zugehörigen Systeme automatisch für den geplanten Zeitraum in den Wartungsmodus zu versetzen.
Groups
Dies ist das von mir abgeänderte Skript was mit Hostgroups funktioniert:
nano zabbix_main_group.pl
#!/usr/bin/perl
use strict;
use Getopt::Std;
use vars qw/ %opt /;
my $url = "http://localhost/api_jsonrpc.php"; # change <zabbix server> to your zabbix server
my $apiuser="username"; # API User's Username
my $apipassword="password"; # API User's password
my $maintenanceid;
#############
# Begin main
#
init();
my $groupname = $opt{s};
my $duration = $opt{d} || 10800;
my $maintname = $opt{n};
# Authenticate against Zabbix for API Maintenance addition
my $auth = newrequest($url, $apiuser, $apipassword);
my $groupid = getgroupid($groupname);
if($opt{r}){
print "Removing maintenance for group $groupname\n";
getmaintid($groupid,$maintname);
exit(0);
}else{
print "Adding maintenance for group $groupname\n";
addmaint($groupid,$duration,$maintname);
}
exit(0);
#########################
# Get command line input
#
sub init(){
my $opt_string = 'hrs:d:n:';
getopts( "$opt_string", \%opt ) or usage();
usage() if $opt{h};
usage() if !$opt{s};
usage() if !$opt{n};
}
#####################
# Print script usage
#
sub usage(){
print STDERR << "EOF";
usage: $0 [-hr] -s groupname [-d duration] -n name
-h : This (help) message
-r : Remove maintenance for specified host
-s groupname : Hostgroupname in Zabbix
-d : Duration of maintenance in seconds. Leave blank to use default.
300 = 5 minutes
1800 = 30 minutes
3600 = 1 hour
10800 = 3 hour (default)
-n name : unique identifier
-s and -n are required
example: $0 -s groupname -d 3600 -n backup
example: $0 -s groupname -r -n backup
EOF
exit;
}
#############################################
# Zabbix API requests require authentication
#
sub newrequest {
my ($url, $user, $password) = @_;
my $authenticate = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"params": {
"password": "$password",
"user": "$user"
},
"jsonrpc": "2.0",
"method": "user.login",
"id": 0
}' $url | grep result | head -n 1 | cut -d '"' -f 8);
my $auth = `$authenticate`;
chomp($auth);
return $auth
}
###################################################
# Subroutine to query Zabbix to get host id
#
sub getgroupid{
my $groupname = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"params": {
"filter": {
"name": "$groupname"
}
},
"jsonrpc": "2.0",
"method": "hostgroup.get",
"auth": "$auth",
"id": 2 }' $url);
my $res = `$process`;
chomp($res);
# print "$res \n\n";
my @output = split(/,/,$res);
my $x=0;
foreach(@output){
if (($output[$x] =~ m/\"name\"/)&&($output[$x] =~ m/$groupname/)){
$output[$x-1] =~ s/\[\{//g;
$output[$x-1] =~ s/"//g;
$output[$x-1] =~ s/groupid://g;
$output[$x-1] =~ s/result://g;
$output[$x-1] =~ s/\{//g;
$groupid = $output[$x-1];
}
$x++;
}
if(!$groupid){
print "WARNING - $groupname not found in maintenance for Zabbix.\n";
exit(1);
}
print "Group ID: ".$groupid."\n";
return $groupid
}
###################################################
# Subroutine to query Zabbix to get maintenance id
#
sub getmaintid{
my $groupid = shift;
my $maintname = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"params": {
"output": "extend",
"selectHosts": "refer",
"selectGroups": "refer",
"groupids": "$groupid"
},
"jsonrpc": "2.0",
"method": "maintenance.get",
"auth": "$auth",
"id": 2 }' $url);
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
my $x=0;
foreach(@output){
if (($output[$x] =~ m/\"name\"/)&&($output[$x] =~ m/ID $maintname/)){
$output[$x-1] =~ s/\[\{//g;
$output[$x-1] =~ s/"//g;
$output[$x-1] =~ s/maintenanceid://g;
$output[$x-1] =~ s/result://g;
$output[$x-1] =~ s/\{//g;
$maintenanceid = $output[$x-1];
remmaint($maintenanceid);
}
$x++;
}
if(!$maintenanceid){
print "WARNING - $groupname not found in maintenance for Zabbix.\n";
exit(1);
}
}
#################################################
# Subroutine to add maintenance window to Zabbix
#
sub addmaint{
$groupid = shift;
$duration = shift;
$maintname = shift;
my $start = time();
my $end = ($start + $duration);
# my $auth = newrequest($url, $apiuser, $apipassword);
my $process = 'curl -k -s -i -X POST -H \'Content-Type: application/json-rpc\' -d "{
\"jsonrpc\":\"2.0\",
\"method\":\"maintenance.create\",
\"params\":[{
\"groupids\":[\"'.$groupid.'\"],
\"hostids\":[],
\"name\":\"000_Trigger Maintenance Mode with ID '.$maintname.' - '.$start.'\",
\"maintenance_type\":\"0\",
\"description\":\"000_Trigger Maintenance Mode for '.$groupname.' set by Action\",
\"active_since\":\"'.$start.'\",
\"active_till\":\"'.$end.'\",
\"timeperiods\": [{
\"timeperiod_type\": 0,
\"start_date\": \"'.$start.'\",
\"period\": '.$duration.'}]
}],
\"auth\":\"'.$auth.'\",
\"id\":3}" '.$url;
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
foreach(@output){
if ($_ =~ m/\"error/){
print "$_\n";
exit(1);
}
print "$_\n" if ($_ =~ m/\"result/);
}
}
#################################################
# Subroutine to remove maintenance window from Zabbix
#
sub remmaint{
$maintenanceid = shift;
my $process = qq(curl -k -s -i -X POST -H 'Content-Type: application/json-rpc' -d '{
"jsonrpc":"2.0",
"method":"maintenance.delete",
"params":["$maintenanceid"],
"auth":"$auth",
"id":2}' $url);
my $res = `$process`;
chomp($res);
my @output = split(/,/,$res);
foreach(@output){
print "$_\n" if ($_ =~ m/\"error/);
print "$_\n" if ($_ =~ m/\"result/);
}
}
Nutzung in Actions
Das Gruppenskript nutze ich Actions um einen ganzen Standort in Wartung zu versetzen:
Im Detail ist das hier beschrieben:
https://znil.net/index.php?title=Zabbix_Standorte_Hostgruppen_bei_Nichterreichbarkeit_automatisch_in_den_Wartungsmodus_setzen_oder_daraus_entfernen
Mit oder ohne Datensammlung
In beiden Skripten gibt es eine Zeile
\"maintenance_type\":\"0\",
Die 0 bedeudet "With data collection". Wollt Ihr das ohne Datensammlung "Without data collection" so ändert die 0 auf eine 1:
\"maintenance_type\":\"1\",