[rrd-users] Re: Can you add more DS "Data Sources" to an already existing rrd database?

Jeff Rodriguez jeff at unixisgod.com
Thu Dec 4 16:26:01 MET 2003


The script is a litte rough around the edges but the basic idea is:

rrdtool dump blah.rrd > blah.xml
./scriptname.pl blah.xml > blah2.xml
(asks you for some input)

rrdtool import blah2.xml blah2.rrd


#!/usr/bin/perl
#    Copyright (C) 2003 Jeff Rodriguez
#
#    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

use warnings;
use strict;

# Get a file from the commandline if it applies
my $file = shift || undef;

# Predefine some variables
my $new_ds_def       = undef;
my @current_ds_list  = ();
my $new_ds_number    = undef;
my %new_ds_values    = ();

my $parsing_cdp_prep = 0;
my @cdp_prep_values  = ();

my $parsing_ds       = 0;
my $parsing_ds_num   = 0;
my @ds_values        = ();


# Define the $xml_input file handle reference
my $xml_input = undef;

if ( defined $file && -e $file )
  {
    open($xml_input,$file) or die "Could not open $file\n";
  }
else
  {
    $xml_input = \*STDIN;
    print STDERR "Paste your XML file here. ^D (unix) or ^Z (win32) to
end\n";
  }

while ( my $xml_line = <$xml_input> )
  {
    print STDERR "Copyright (C) 2003 Jeff Rodriguez\n";

    # Remove newlines
    chomp $xml_line;
    chop $xml_line if substr($xml_line, -1) eq "\r";

    if ( $xml_line =~ /^\s+<ds>$/ )
      {
        $parsing_ds = 1;
      }
    if ( $parsing_ds == 1 )
      {
        $ds_values[$parsing_ds_num] .= "$xml_line\n";
      }
    if ( $xml_line =~ /^\s+<\/ds>$/ )
      {
        $parsing_ds = 0;
        $parsing_ds_num++;
        $ds_values[$parsing_ds_num] .= "$xml_line\n";
        next;
      }

    # See if this is the name of a DS
    $xml_line =~ /\s+<name> (.+?) <\/name>/;
    if ( defined $1 )
      {
        if ( $#current_ds_list == -1 )
          {
            push(@current_ds_list, $1);
          }
        else
          {
            push(@current_ds_list, $1) if $1 ne $current_ds_list[-1];
          }
      }

    # See if we're at the end of the DS definition list
    if ( $xml_line =~ /Round Robin Archives/ )
      {
        # Well, we are ask where they want the DS
        print STDERR "You currently have " . ($#current_ds_list + 1) . "
Data Source(s).\n";
        print STDERR "Where do you want the new DS?\n";
        print STDERR "1. Before '$current_ds_list[0]'.\n";

        # List each DS
        for (my $i = 2; $i <= ( $#current_ds_list + 2 ); $i++)
          {
            print STDERR "$i. After '$current_ds_list[$i - 2]'.\n";
          }

        # Get their choice from the command line
        print STDERR "? ";
        while ( !defined $new_ds_number )
          {
            my $number = <STDIN>;
            chomp $number;
            $number =~ /(\d+)/;
            if ( defined $1 && $1 <= ( $#current_ds_list + 2 ) && $1 > 0 )
              {
                $new_ds_number = $1;
                if ( $1 == 1 )
                  {
                    print STDERR "Your new Data Source will be before
'$current_ds_list[0]'.\n";
                  }
                else
                  {
                    print STDERR "Your new Data Source will be after
'$current_ds_list[$1 - 2]'.\n";
                  }
              }
            else
              {
                print STDERR "Invalid entry. Enter a valid choice: ";
                next;
              }
          }

        # Get the new DS values
        while ( keys %new_ds_values != 5 )
          {
            print STDERR "Enter the Data Source Definition for your new
DS\n";
            print STDERR "DS:";
            my $new_ds_definition = <STDIN>;
            chomp $new_ds_definition;
            $new_ds_definition =~
/^([a-zA-Z0-9_]{1,19}):(GAUGE|COUNTER|DERIVE|ABSOLUTE):(\d+?):(U|\d+?):(U|\d
+?)$/;
            if ( defined $1 && defined $2 && defined $3 && defined $4 &&
defined $5 )
              {
                if ( grep(/^$1$/, @current_ds_list) )
                  {
                    print STDERR "The data source '$1' already exists!\n";
                  }
                else
                  {
                    $new_ds_values{name}      = $1;
                    $new_ds_values{type}      = $2;
                    $new_ds_values{heartbeat} = $3;

                    if ( $4 eq "U" )
                      {
                        $new_ds_values{min}   = "NaN";
                      }
                    else
                      {
                        $new_ds_values{min}   = $4;
                      }

                    if ( $5 eq "U" )
                      {
                        $new_ds_values{max}   = "NaN";
                      }
                    else
                      {
                        $new_ds_values{max}   = $5;
                      }

                  }
              }
            else
              {
                next;
              }

          }

        # Inject the new Data Source
        splice(@ds_values, ($new_ds_number - 1), 0, <<EndDataSource
        <ds>
                <name> $new_ds_values{name} </name>
                <type> $new_ds_values{type} </type>
                <minimal_heartbeat> $new_ds_values{heartbeat}
</minimal_heartbeat>
                <min> $new_ds_values{min} </min>
                <max> $new_ds_values{max} </max>

                <!-- PDP Status -->
                <last_ds> UNKN </last_ds>
                <value> 0.0000000000e+00 </value>
                <unknown_sec> 0 </unknown_sec>
        </ds>

EndDataSource
);
        foreach my $ds_value (@ds_values)
          {
            print "$ds_value\n";
          }

      }

    # If the new_ds_number is defined, we've finished parsing the data
sources and it's time to start adding
    if ( defined $new_ds_number )
      {

        if ( $xml_line =~ /<\/cdp_prep>/ )
          {
            $parsing_cdp_prep = 0;
            splice(@cdp_prep_values, ($new_ds_number - 1), 0, "
<ds><value> NaN </value>  <unknown_datapoints> 0
</unknown_datapoints></ds>");
            foreach my $cdp_prep_value (@cdp_prep_values)
              {
                print "$cdp_prep_value\n";
              }
            @cdp_prep_values = ();
          }

        # Test to see if we're parsig a cdp_prep
        if ( $parsing_cdp_prep == 1 )
          {
            push(@cdp_prep_values, $xml_line);
          }

        # Test to see if this line is a <cdp_prep> line
        if ( $xml_line =~ /<cdp_prep>/ )
          {
            $parsing_cdp_prep = 1;
            print "$xml_line\n";
          }


        # This checks to see if xml_line is a database entry
        if ( $xml_line =~ /^(.+?<row>)(.+?)(<\/row>.*)$/ )
          {
            my @datasources_in_entry = split(/<\/v>/, $2);
            splice(@datasources_in_entry, ($new_ds_number - 1), 0, "<v> 0
");
            my $new_line = join("</v>", @datasources_in_entry);
            print "$1$new_line</v>$3\n";
          }
        else
          {
            print "$xml_line\n" unless $parsing_cdp_prep == 1;
          }
      }
    else
      {
        print "$xml_line\n" unless $parsing_ds == 1;
      }
  }


--
Unsubscribe mailto:rrd-users-request at list.ee.ethz.ch?subject=unsubscribe
Help        mailto:rrd-users-request at list.ee.ethz.ch?subject=help
Archive     http://www.ee.ethz.ch/~slist/rrd-users
WebAdmin    http://www.ee.ethz.ch/~slist/lsg2.cgi



More information about the rrd-users mailing list