2017-05-20 15:26:21 +02:00
|
|
|
|
#!@PERL@
|
|
|
|
|
## @PKG_NAME@–@PKG_VERSION@ rrd_convert.pl
|
2017-05-20 15:29:39 +02:00
|
|
|
|
## Copyright (c) 2006-2015 Joerg Linge (http://www.pnp4nagios.org)
|
2017-05-20 15:26:21 +02:00
|
|
|
|
##
|
|
|
|
|
## This program is free software; you can redistribute it and/or
|
|
|
|
|
## modify it under the terms of the GNU General Public License
|
|
|
|
|
## as published by the Free Software Foundation; either version 2
|
|
|
|
|
## of the License, or (at your option) any later version.
|
|
|
|
|
##
|
|
|
|
|
## This program is distributed in the hope that it will be useful,
|
|
|
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
## GNU General Public License for more details.
|
|
|
|
|
##
|
|
|
|
|
## You should have received a copy of the GNU General Public License
|
|
|
|
|
## along with this program; if not, write to the Free Software
|
|
|
|
|
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
|
|
@PERL_LIB_PATH_CODE@
|
|
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
use Getopt::Long;
|
|
|
|
|
use Time::HiRes qw(gettimeofday tv_interval);
|
|
|
|
|
use File::Find;
|
|
|
|
|
use File::Copy;
|
|
|
|
|
|
|
|
|
|
if( $< == 0 ){
|
|
|
|
|
print "dont try this as root \n";
|
|
|
|
|
exit 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Some global Vars
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
my %conf = (
|
|
|
|
|
CFG_DIR => "@sysconfdir@/",
|
|
|
|
|
RRDPATH => "@PERFDATA_DIR@",
|
|
|
|
|
RRDTOOL => "@RRDTOOL@",
|
|
|
|
|
LOG_LEVEL => 0,
|
|
|
|
|
DRY_RUN => 0,
|
|
|
|
|
FORCE => 0,
|
|
|
|
|
RRD_BACKUP => 1,
|
|
|
|
|
RRD_STORAGE_TYPE => "SINGLE",
|
|
|
|
|
TMP_DIR => '/tmp/rrd_convert',
|
|
|
|
|
RRD_DAEMON_OPTS => "",
|
|
|
|
|
XML_MAX_AGE => 3600,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Getopt::Long::Configure('bundling');
|
2017-10-20 17:10:51 +02:00
|
|
|
|
my ( $opt_V, $opt_h, $opt_c, $opt_l, $opt_x, $opt_p, $opt_s, $opt_o, $opt_r );
|
2017-05-20 15:26:21 +02:00
|
|
|
|
# defaults
|
|
|
|
|
$opt_x = 1;
|
|
|
|
|
|
|
|
|
|
GetOptions(
|
|
|
|
|
"V|version" => \$opt_V,
|
|
|
|
|
"h|help" => \$opt_h,
|
|
|
|
|
"c|check_command=s" => \$opt_c,
|
|
|
|
|
"p|cfg_dir=s" => \$opt_p,
|
|
|
|
|
"l|list_commands" => \$opt_l,
|
2017-10-20 17:10:51 +02:00
|
|
|
|
"s|stepwise" => \$opt_s,
|
2017-05-20 15:26:21 +02:00
|
|
|
|
"x|no_structure_check" => \$opt_x,
|
2017-10-20 17:10:51 +02:00
|
|
|
|
"o|log_old_xml" => \$opt_o,
|
2017-05-20 15:26:21 +02:00
|
|
|
|
"d|dry-run" => \$conf{DRY_RUN},
|
|
|
|
|
"t|tmp_dir=s" => \$conf{TMP_DIR},
|
|
|
|
|
"force" => \$conf{FORCE},
|
2017-10-20 17:10:51 +02:00
|
|
|
|
"r|read=s" => \$opt_r,
|
2017-05-20 15:26:21 +02:00
|
|
|
|
);
|
|
|
|
|
|
2017-10-20 17:10:51 +02:00
|
|
|
|
if (defined($opt_r)) {
|
|
|
|
|
$opt_c = "ALL";
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-20 15:26:21 +02:00
|
|
|
|
print_help() if $opt_h;
|
|
|
|
|
print_help_opt_p() if !$opt_p;
|
2017-10-20 17:10:51 +02:00
|
|
|
|
print_help() if (!$opt_c and !$opt_l) and (!$opt_r);
|
2017-05-20 15:26:21 +02:00
|
|
|
|
print_version() if $opt_V;
|
|
|
|
|
|
|
|
|
|
if($opt_p){
|
|
|
|
|
$conf{CFG_DIR} = $opt_p;
|
|
|
|
|
}
|
|
|
|
|
parse_config($conf{CFG_DIR}."/process_perfdata.cfg");
|
|
|
|
|
if ( $conf{RRD_DAEMON_OPTS} ){
|
|
|
|
|
$conf{RRD_DAEMON_OPTS} = "--daemon=".$conf{RRD_DAEMON_OPTS};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my @STRUCT;
|
|
|
|
|
my %FILEHANDLE;
|
|
|
|
|
|
|
|
|
|
my @commands; # list of commands
|
|
|
|
|
my @worklist; # list of found xml files
|
|
|
|
|
|
|
|
|
|
my %ds_list;
|
|
|
|
|
my %original_ds_list;
|
|
|
|
|
my $max_age = time() - $conf{XML_MAX_AGE};
|
|
|
|
|
|
|
|
|
|
my %stats = (
|
|
|
|
|
'rrd_in' => 0,
|
|
|
|
|
'rrd_out' => 0,
|
|
|
|
|
'old_xml' => 0,
|
|
|
|
|
'xml_without_rrd' => 0,
|
|
|
|
|
'runtime' => 0,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
main();
|
|
|
|
|
|
|
|
|
|
sub main{
|
|
|
|
|
check_storage_type();
|
2017-10-20 17:10:51 +02:00
|
|
|
|
if ($opt_o) {
|
|
|
|
|
create_dir($conf{TMP_DIR});
|
|
|
|
|
open(OLDXMLLOG, ">", $conf{TMP_DIR}."/pnp_old_xml_files.list");
|
|
|
|
|
print OLDXMLLOG "- generated by rrd_convert.pl - \n";
|
|
|
|
|
print OLDXMLLOG "The following XML files are older than $conf{XML_MAX_AGE} seconds:\n\n";
|
|
|
|
|
}
|
|
|
|
|
build_worklist();
|
|
|
|
|
close(OLDXMLLOG);
|
2017-05-20 15:26:21 +02:00
|
|
|
|
summary();
|
|
|
|
|
if($opt_l){ # List commands and exit
|
|
|
|
|
summary_command_list();
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
if($#worklist+1 > 0 ){
|
2017-10-20 17:10:51 +02:00
|
|
|
|
my $question = "Start converter? " . ($opt_s ? "(Each conversion will be prompted.) " : "");
|
|
|
|
|
my $answer = read_choice($question . "[n|y]");
|
2017-05-20 15:26:21 +02:00
|
|
|
|
unless ( $answer =~ m/^y$/i ){
|
|
|
|
|
print "Exit...\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
print "Check Command '".$opt_c."' not found in any XML File\n";
|
|
|
|
|
print "\n";
|
|
|
|
|
print "\n";
|
|
|
|
|
summary_command_list();
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
check_custom_template();
|
|
|
|
|
write_custom_template();
|
|
|
|
|
my $t0 = [gettimeofday];
|
|
|
|
|
my $i = 0;
|
2017-10-20 17:10:51 +02:00
|
|
|
|
my $answered = "";
|
2017-05-20 15:26:21 +02:00
|
|
|
|
foreach my $xmlfile ( @worklist ) {
|
2017-10-20 17:10:51 +02:00
|
|
|
|
if($opt_s && ($answered !~ $xmlfile)){
|
|
|
|
|
my $answer = read_choice("Continue with $xmlfile [n|y]?");
|
|
|
|
|
unless ( $answer =~ m/^y$/i ){
|
|
|
|
|
print "Exit... (remember to remove the custom template, if created in this run!)\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
$answered = $xmlfile;
|
|
|
|
|
}
|
2017-05-20 15:26:21 +02:00
|
|
|
|
$i++;
|
|
|
|
|
undef %ds_list;
|
|
|
|
|
undef %original_ds_list;
|
|
|
|
|
my($host,$service) = parse_xml_filename($xmlfile);
|
|
|
|
|
my ($rrdfile) = $xmlfile =~ /^(.*)\.xml$/;
|
|
|
|
|
$rrdfile .= ".rrd";
|
|
|
|
|
if(-r $rrdfile){
|
|
|
|
|
create_dir($conf{TMP_DIR});
|
|
|
|
|
my $dumpfile = sprintf("%s/%s-%s.dump",$conf{TMP_DIR},$host,$service);
|
|
|
|
|
print "File ".$i."/".($#worklist+1)."\n";
|
|
|
|
|
rrdtool_dump($rrdfile,$dumpfile);
|
|
|
|
|
parse_pnp_xml($xmlfile);
|
|
|
|
|
build_ds_list($rrdfile);
|
|
|
|
|
next if check_ds_list();
|
|
|
|
|
open_files($host,$service);
|
|
|
|
|
manipulate_rrd_dump($dumpfile);
|
|
|
|
|
close_files();
|
|
|
|
|
restore_files($host,$service);
|
|
|
|
|
backup_rrd_file($rrdfile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
my $t1 = [gettimeofday];
|
|
|
|
|
$stats{runtime} = tv_interval $t0, $t1;
|
|
|
|
|
print "DONE\n";
|
|
|
|
|
stats();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub build_ds_list{
|
|
|
|
|
my $rrdfile = shift;
|
|
|
|
|
my @info;
|
|
|
|
|
@info = `$conf{'RRDTOOL'} info $rrdfile`;
|
|
|
|
|
if( $? > 0 ){
|
|
|
|
|
print "ERROR: $conf{'RRDTOOL'} info $rrdfile returns with $?\n";
|
|
|
|
|
exit 1;
|
|
|
|
|
}
|
|
|
|
|
foreach(@info){
|
|
|
|
|
if(m/ds\[(\d+)\]\.type/ ) {
|
|
|
|
|
$ds_list{$1} = $1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
my $test = keys %ds_list;
|
|
|
|
|
%original_ds_list = %ds_list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub check_ds_list{
|
|
|
|
|
my $rrd_ds_count = keys %ds_list;
|
|
|
|
|
my $xml_ds_count = $#STRUCT;
|
|
|
|
|
if($rrd_ds_count == $xml_ds_count){
|
|
|
|
|
return 0;
|
|
|
|
|
}elsif($rrd_ds_count <= $xml_ds_count && $opt_x){
|
|
|
|
|
printf("OK: RRD contains '%s' DS but XML contains '%s'. Convert forced by --no_structure_check\n",$rrd_ds_count,$xml_ds_count);
|
|
|
|
|
return 0;
|
|
|
|
|
}else{
|
|
|
|
|
printf ("ERROR: RRD Structure mismatch. DS Count is '%s' but should be '%s'\n",$rrd_ds_count,$xml_ds_count);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-20 17:10:51 +02:00
|
|
|
|
sub build_worklist {
|
|
|
|
|
if ($opt_r) {
|
|
|
|
|
process_xml_files($opt_r);
|
|
|
|
|
close XMLLIST;
|
|
|
|
|
}else{
|
|
|
|
|
find(\&find_xml_files, $conf{RRDPATH});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# bulk mode, find all XML files
|
|
|
|
|
sub find_xml_files{
|
2017-05-20 15:26:21 +02:00
|
|
|
|
if(m/.xml$/){
|
|
|
|
|
#printf("File: %s\n",$File::Find::name);
|
2017-10-20 17:10:51 +02:00
|
|
|
|
xml2worklist($File::Find::name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# file mode, process file with XML filenames
|
|
|
|
|
sub process_xml_files{
|
|
|
|
|
my $xmllist = shift;
|
|
|
|
|
-r $xmllist or die "Cannot open $xmllist: $!";
|
|
|
|
|
open XMLLIST, "<$opt_r";
|
|
|
|
|
foreach (<XMLLIST>) {
|
|
|
|
|
my $file = $_;
|
|
|
|
|
chomp($file);
|
|
|
|
|
m/.xml$/ && xml2worklist($file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub xml2worklist {
|
|
|
|
|
my $xmlfile = shift;
|
|
|
|
|
my ($rrdfile) = $xmlfile =~ /^(.*)\.xml$/;
|
|
|
|
|
$rrdfile .= ".rrd";
|
|
|
|
|
my $mtime = (stat($xmlfile))[9];
|
|
|
|
|
if ( $mtime < $max_age ){
|
|
|
|
|
$stats{old_xml}++;
|
|
|
|
|
if ($opt_o) {
|
|
|
|
|
print OLDXMLLOG $xmlfile . ": " . scalar localtime($mtime) ."\n";
|
2017-05-20 15:26:21 +02:00
|
|
|
|
}
|
2017-10-20 17:10:51 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
open(XML, $xmlfile);
|
|
|
|
|
while (<XML>) {
|
|
|
|
|
if(/TEMPLATE>(.*)</){
|
|
|
|
|
my ($t) = split("!",$1);
|
|
|
|
|
push(@commands,$t);
|
|
|
|
|
if(( defined $opt_c) and ($t =~ /^$opt_c$/)){
|
|
|
|
|
if( -e $rrdfile ){
|
|
|
|
|
#print "Found: ".$t." in ".$xmlfile."\n";
|
|
|
|
|
push(@worklist,$xmlfile);
|
|
|
|
|
}else{
|
|
|
|
|
$stats{xml_without_rrd}++;
|
2017-05-20 15:26:21 +02:00
|
|
|
|
}
|
2017-10-20 17:10:51 +02:00
|
|
|
|
}elsif (( defined $opt_c) and ($opt_c eq 'ALL') ) {
|
|
|
|
|
if( -e $rrdfile ){
|
|
|
|
|
# Keyword 'ALL' retunrs all XML Files
|
|
|
|
|
push(@worklist,$xmlfile);
|
|
|
|
|
}else{
|
|
|
|
|
$stats{xml_without_rrd}++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-20 15:26:21 +02:00
|
|
|
|
}
|
2017-10-20 17:10:51 +02:00
|
|
|
|
close(XML);
|
2017-05-20 15:26:21 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub parse_xml_filename{
|
|
|
|
|
my $xmlfile = shift;
|
|
|
|
|
$_ = $xmlfile;
|
|
|
|
|
if( m/([^\/]+)\/([^\/]+)\.xml$/i ){
|
|
|
|
|
return ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sub summary{
|
|
|
|
|
my %seen;
|
|
|
|
|
my @uniqed = grep !$seen{$_}++, @commands;
|
|
|
|
|
print "\n";
|
|
|
|
|
printf "%-40s %s\n" ,"Search pattern",$opt_c if( defined ($opt_c) );
|
|
|
|
|
printf "%-40s %s\n" ,"XML Files analyzed",$#commands+1;
|
|
|
|
|
printf "%-40s %s\n" ,"XML Files found",$#worklist+1;
|
|
|
|
|
printf "%-40s %s\n" ,"XML Files without RRD",$stats{'xml_without_rrd'};
|
|
|
|
|
printf "%-40s %s\n" ,"Old XML Files ignored",$stats{'old_xml'};
|
|
|
|
|
printf "%-40s %s\n" ,"Number of unique check_commands",$#uniqed+1;
|
|
|
|
|
if($conf{DRY_RUN} == 1){
|
|
|
|
|
printf "%-40s %s\n" ,"Dry run?","[YES]";
|
|
|
|
|
printf "%-40s %s\n" ,"Temp Directory",$conf{TMP_DIR};
|
|
|
|
|
print "\n\n";
|
|
|
|
|
print "This is only a 'dry run'. The new RRD Files are stored in '$conf{TMP_DIR}'\n";
|
|
|
|
|
print "\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub summary_command_list{
|
|
|
|
|
my %seen;
|
|
|
|
|
my @uniqed = grep !$seen{$_}++, @commands;
|
|
|
|
|
printf "\\ List of Check Commands\n";
|
|
|
|
|
foreach my $key (sort { $seen{$b} <=> $seen{$a} } keys %seen ) {
|
|
|
|
|
printf " |- %-36s %5s\n",$key,$seen{$key};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub stats{
|
|
|
|
|
print "\n\n \\Statistics:\n";
|
|
|
|
|
foreach my $key (sort { $stats{$b} cmp $stats{$a} } keys %stats ) {
|
|
|
|
|
printf " |- %-15s %s\n",$key,$stats{$key};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub create_dir{
|
|
|
|
|
my $dir = shift;
|
|
|
|
|
unless ( -d "$dir" ) {
|
|
|
|
|
unless ( mkdir "$dir" ) {
|
|
|
|
|
print "ERROR: $dir is not writable\n";
|
|
|
|
|
exit 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub open_files(){
|
|
|
|
|
my $host = shift;
|
|
|
|
|
my $service = shift;
|
|
|
|
|
foreach my $ds (keys %ds_list){
|
|
|
|
|
my $file = sprintf("%s/%s-%s-%s.restore",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME});
|
|
|
|
|
#print "Open Filehandle ".$file."\n";
|
|
|
|
|
open($FILEHANDLE{$ds}, ">", $file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub close_files(){
|
|
|
|
|
foreach my $ds (keys %ds_list){
|
|
|
|
|
#$ds--;
|
|
|
|
|
#print "Close Filehandle ".$STRUCT[$ds]{NAME}."\n";
|
|
|
|
|
close($FILEHANDLE{$ds});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub write_to_files{
|
|
|
|
|
my $data = shift;
|
|
|
|
|
foreach my $ds (keys %ds_list){
|
|
|
|
|
print { $FILEHANDLE{$ds} } $data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub restore_files(){
|
|
|
|
|
my $host = shift;
|
|
|
|
|
my $service = shift;
|
|
|
|
|
my $err;
|
|
|
|
|
$| = 1;
|
|
|
|
|
print "Restoring File\n";
|
|
|
|
|
foreach my $ds (keys %ds_list){
|
|
|
|
|
my $rrdfile = '';
|
|
|
|
|
my $restorefile = sprintf("%s/%s-%s-%s.restore",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME});
|
|
|
|
|
if( $conf{'DRY_RUN'} == 1 ){
|
|
|
|
|
$rrdfile = sprintf("%s/%s/%s_%s.rrd",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME});
|
|
|
|
|
create_dir(sprintf("%s/%s", $conf{TMP_DIR},$host ));
|
|
|
|
|
}else{
|
|
|
|
|
$rrdfile = sprintf("%s/%s/%s_%s.rrd",$conf{RRDPATH},$host,$service,$STRUCT[$ds]{NAME});
|
|
|
|
|
}
|
|
|
|
|
print "$rrdfile\n";
|
|
|
|
|
$err = system("$conf{'RRDTOOL'} restore -f '$restorefile' '$rrdfile'");
|
|
|
|
|
if($err){
|
|
|
|
|
printf("RRDtool Error: %s\n",$err);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
unlink($restorefile);
|
|
|
|
|
$stats{rrd_out}++;
|
|
|
|
|
}
|
|
|
|
|
print "... done\n";
|
|
|
|
|
$| = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub backup_rrd_file{
|
|
|
|
|
my $rrdfile = shift;
|
2017-10-20 17:10:51 +02:00
|
|
|
|
if ( $conf{RRD_BACKUP} == 1 && $conf{'DRY_RUN'} == 0 ){
|
2017-05-20 15:26:21 +02:00
|
|
|
|
move($rrdfile, $rrdfile.".backup");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub parse_pnp_xml{
|
|
|
|
|
my $xmlfile = shift;
|
|
|
|
|
undef @STRUCT;
|
|
|
|
|
#print "reading $xmlfile\n";
|
|
|
|
|
open(XML, $xmlfile);
|
|
|
|
|
my $DATASOURCE = 0;
|
|
|
|
|
while (<XML>) {
|
|
|
|
|
if(/<DATASOURCE>/){
|
|
|
|
|
$DATASOURCE++;
|
|
|
|
|
}
|
|
|
|
|
if(/<RRD>/){
|
|
|
|
|
$DATASOURCE = 0;
|
|
|
|
|
}
|
|
|
|
|
if(/<([A-Z_]+)>(.*)<\/[A-Z_]+>/ && $DATASOURCE != -1){
|
|
|
|
|
$STRUCT[$DATASOURCE]{$1} = $2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
close(XML);
|
|
|
|
|
return @STRUCT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub rrdtool_dump{
|
|
|
|
|
my $rrdfile = shift;
|
|
|
|
|
my $dumpfile = shift;
|
|
|
|
|
my $err;
|
|
|
|
|
print "RRDtool dump to $dumpfile\n";
|
|
|
|
|
if ( $conf{RRD_DAEMON_OPTS} ){
|
|
|
|
|
$err = system("$conf{'RRDTOOL'} dump $conf{RRD_DAEMON_OPTS} $rrdfile > $dumpfile");
|
|
|
|
|
}else{
|
|
|
|
|
$err = system("$conf{'RRDTOOL'} dump $rrdfile > $dumpfile");
|
|
|
|
|
}
|
|
|
|
|
if($err){
|
|
|
|
|
printf("RRDtool Error: %s\n",$err);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
$stats{rrd_in}++;
|
|
|
|
|
return $dumpfile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub manipulate_rrd_dump{
|
|
|
|
|
my $tmpfile = shift;
|
|
|
|
|
my $i = 0;
|
|
|
|
|
open (XML,$tmpfile);
|
|
|
|
|
my @ROW = ();
|
|
|
|
|
my $tmpds = 1;
|
|
|
|
|
my $inside_ds_block = 0;
|
|
|
|
|
print "Manipulating $tmpfile\n";
|
|
|
|
|
while (<XML>){
|
|
|
|
|
$i++;
|
|
|
|
|
unless ( $i % 5000 ){
|
|
|
|
|
$| = 1; print "."; $| = 0;
|
|
|
|
|
}
|
|
|
|
|
my $d = $_;
|
|
|
|
|
#
|
|
|
|
|
# A Data Row
|
|
|
|
|
if(m/<row>/){
|
|
|
|
|
m/(.*<row>)/;
|
|
|
|
|
my $rowstart = $1;
|
|
|
|
|
@ROW = m{<v>([^<].*?)<\/v>}gc;
|
|
|
|
|
my $fh = 1;
|
|
|
|
|
foreach my $VAL (@ROW){
|
|
|
|
|
undef %ds_list;
|
|
|
|
|
$ds_list{$fh} = $fh;
|
|
|
|
|
write_to_files($rowstart."<v>".$VAL."</v></row>\n");
|
|
|
|
|
$fh++;
|
|
|
|
|
}
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if(m/<ds>/){
|
|
|
|
|
$inside_ds_block = 1;
|
|
|
|
|
undef %ds_list;
|
|
|
|
|
$ds_list{$tmpds} = $tmpds;
|
|
|
|
|
write_to_files($d);
|
|
|
|
|
$tmpds++;
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if(m/<cdp_prep>/){
|
|
|
|
|
write_to_files($d);
|
|
|
|
|
$inside_ds_block = 0;
|
|
|
|
|
$tmpds = 1;
|
|
|
|
|
%ds_list = %original_ds_list;
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if(m/<\/ds>/){
|
|
|
|
|
write_to_files($d);
|
|
|
|
|
$inside_ds_block = 0;
|
|
|
|
|
# write to all files alter </ds>
|
|
|
|
|
%ds_list = %original_ds_list;
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if(m/<\/database>/){
|
|
|
|
|
# write to all files alter </database>
|
|
|
|
|
%ds_list = %original_ds_list;
|
|
|
|
|
write_to_files($d);
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if($inside_ds_block == 1){
|
|
|
|
|
# rename DS
|
|
|
|
|
$d =~ s/<name>(.*)<\/name>/<name> 1 <\/name>/;
|
|
|
|
|
}
|
|
|
|
|
write_to_files($d);
|
|
|
|
|
}
|
|
|
|
|
close(XML);
|
|
|
|
|
print "... done $i lines\n";
|
|
|
|
|
unlink($tmpfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Parse process_perfdata.cfg
|
|
|
|
|
#
|
|
|
|
|
sub parse_config {
|
|
|
|
|
my $config_file = shift;
|
|
|
|
|
my $line = 0;
|
|
|
|
|
if( ! -e $config_file ){
|
|
|
|
|
print "$config_file not found\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
if ( -e $config_file ) {
|
|
|
|
|
open CFG, '<', "$config_file";
|
|
|
|
|
while (<CFG>) {
|
|
|
|
|
$line++;
|
|
|
|
|
chomp;
|
|
|
|
|
s/ //g;
|
|
|
|
|
next if /^#/;
|
|
|
|
|
next if /^$/;
|
|
|
|
|
s/#.*//;
|
|
|
|
|
|
|
|
|
|
if (/^(.*)=(.*)$/) {
|
|
|
|
|
if ( defined $conf{$1} ) {
|
|
|
|
|
$conf{$1} = $2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
close CFG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Change RRD_STORAGE_TYPE to MULTIPLE
|
|
|
|
|
#
|
|
|
|
|
sub change_config {
|
|
|
|
|
my $cfg_file = $conf{'CFG_DIR'}."/process_perfdata.cfg";
|
|
|
|
|
my $error = system("sed -i -e ".'s/\s*RRD_STORAGE_TYPE\s*=\s*SINGLE/RRD_STORAGE_TYPE=MULTIPLE/i'." $cfg_file");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub check_storage_type{
|
|
|
|
|
if($conf{'RRD_STORAGE_TYPE'} eq "MULTIPLE"){
|
2017-10-20 17:10:51 +02:00
|
|
|
|
print "RRD_STORAGE_TYPE is already globally set to ".$conf{'RRD_STORAGE_TYPE'}."\n";
|
2017-05-20 15:26:21 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sub check_custom_template {
|
|
|
|
|
my $command = $opt_c;
|
|
|
|
|
if ( $conf{DRY_RUN} == 1 ){
|
|
|
|
|
print "No config check while DRY_RUN = 1\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ( $command eq "ALL" ){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
my $config_file = $conf{'CFG_DIR'}."/check_commands/".$command.".cfg";
|
|
|
|
|
my $storage_type = "MULTIPLE";
|
|
|
|
|
if ( -e $config_file && $conf{'FORCE'} == 0 ) {
|
|
|
|
|
print "\nConfig for command $command does already exist ($config_file)\n\n";
|
|
|
|
|
exit 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub write_custom_template {
|
2017-10-20 17:10:51 +02:00
|
|
|
|
# do not write custom template in --read mode
|
|
|
|
|
return if $opt_r;
|
2017-05-20 15:26:21 +02:00
|
|
|
|
my $command = $opt_c;
|
|
|
|
|
if ( $conf{DRY_RUN} == 1 ){
|
|
|
|
|
print "No config check while DRY_RUN = 1\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ( $opt_c eq "ALL"){
|
|
|
|
|
change_config();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
my $config_file = $conf{'CFG_DIR'}."/check_commands/".$command.".cfg";
|
|
|
|
|
my $storage_type = "MULTIPLE";
|
|
|
|
|
open(CFG, ">", $config_file);
|
|
|
|
|
print CFG "# Generated by rrd_convert.pl @PKG_VERSION@\n";
|
|
|
|
|
print CFG "RRD_STORAGE_TYPE = MULTIPLE\n";
|
|
|
|
|
close(CFG);
|
|
|
|
|
if ( -s $config_file ) {
|
|
|
|
|
print "\nConfig for command $command created ($config_file)\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sub read_choice{
|
|
|
|
|
my $question = shift;
|
|
|
|
|
print $question.":";
|
|
|
|
|
my $answer = <STDIN>;
|
|
|
|
|
chomp $answer;
|
|
|
|
|
return $answer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub print_help{
|
|
|
|
|
print "Usage: $0 --check_command=<nagios_check_command>\n";
|
|
|
|
|
print " --cfg_dir=<path_to_pnp_etc_dir>\n";
|
|
|
|
|
print " [ --list_commands ]\n";
|
|
|
|
|
print " [ --dry-run ]\n";
|
|
|
|
|
print " [ --tmp_dir=<temp directory> ]\n";
|
|
|
|
|
print " [ --no_structure_check ]\n";
|
2017-10-20 17:10:51 +02:00
|
|
|
|
print " [ --log_old_xml ]\n";
|
|
|
|
|
print " [ --stepwise ]\n";
|
|
|
|
|
print " [ --read=<file with XML filenames> ]\n";
|
2017-05-20 15:26:21 +02:00
|
|
|
|
print "\n";
|
2017-10-20 17:10:51 +02:00
|
|
|
|
print "This script is used to switch to RRD_STORAGE_TYPE = MULTIPLE for all RRDs/a given Nagios Check Command/single RRDs \n";
|
2017-05-20 15:26:21 +02:00
|
|
|
|
print "More info online http://docs.pnp4nagios.org/pnp-0.6/rrd_convert\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub print_help_opt_p{
|
|
|
|
|
print "\n";
|
|
|
|
|
print "--cfg_dir not set\n";
|
|
|
|
|
print "Please provide the path to your PNP4Nagios config directory\n";
|
|
|
|
|
print "\n";
|
|
|
|
|
print_help();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub print_version{
|
|
|
|
|
print "Version @PKG_VERSION@\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|