<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/usr/bin/perl 
#+-----------------------------------------------------------------------------+
#+ $Source: /var/repository/MONITOR/MiscScripts/add_ds.pl,v $
#+-----------------------------------------------------------------------------+
#+ Description: Type definitions for strings
#+-----------------------------------------------------------------------------+
#+ $Author: jrod $
#+-----------------------------------------------------------------------------+
#+ $Revision: 1.1.1.1 $
#+-----------------------------------------------------------------------------+
#+ Copyright (C) 2004  AetherSoft.org
#+-----------------------------------------------------------------------------+
#+ 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.
#+-----------------------------------------------------------------------------+


# +----------------------------------------------------------------------------+
# + {{{ Modules
# +----------------------------------------------------------------------------+
use strict;
use warnings;
use RRDs;
use Pod::Usage;
use Getopt::Long;
# +----------------------------------------------------------------------------+
# + }}} Modules
# +----------------------------------------------------------------------------+

# +----------------------------------------------------------------------------+
# + {{{ Global Variables
# +----------------------------------------------------------------------------+
my %options               = ();
   $options{'source'}     = undef;
   $options{'ds'}         = undef;
my %extraOpts             = ();
   $extraOpts{'help'}     = 0;
   $extraOpts{'man'}      = 0;
   $extraOpts{'verbose'}  = 0;
   $extraOpts{'nobackup'} = 0;
my $getoptResult          = undef;
# +----------------------------------------------------------------------------+
# + }}} Global Variables
# +----------------------------------------------------------------------------+

# +----------------------------------------------------------------------------+
# + {{{ Get Options
# +----------------------------------------------------------------------------+
GetOptions( 'source=s' =&gt; \$options{'source'},
            'ds=s'     =&gt; \$options{'ds'},
            'help'     =&gt; \$extraOpts{'help'},
            'man'      =&gt; \$extraOpts{'man'},
            'verbose'  =&gt; \$extraOpts{'verbose'},
            'nobackup' =&gt; \$extraOpts{'nobackup'} ) or pod2usage(2);

pod2usage(1) if $extraOpts{'help'};
pod2usage(-exitstatus =&gt; 0, -verbose =&gt; 2) if $extraOpts{'man'};
# +----------------------------------------------------------------------------+
# + }}} Get Options
# +----------------------------------------------------------------------------+

# +----------------------------------------------------------------------------+
# + {{{ Validate Options
# +----------------------------------------------------------------------------+
# Source Defined
pod2usage(-exitstatus =&gt; 1, -verbose =&gt; 1, -msg =&gt; "No source RRD defined.")
  if ( not defined $options{'source'} );

# Datasource Defined
pod2usage(-exitstatus =&gt; 1, -verbose =&gt; 1, -msg =&gt; "No Datasource defined.")
  if ( not defined $options{'ds'} );

# Existing RRD
die "RRD does not exist: $options{'source'}\n" if ( not -e $options{'source'} );

# Writable RRD
die "Cannot write to: $options{'source'}\n" if ( not -e $options{'source'} );

# Backup file existence
if ( $extraOpts{'nobackup'} and -e $options{'source'})
{
  die "Backup file exists: $options{'source'}.bak\n";
}

# Datasource
if ( $options{'ds'} =~ /^DS:([a-zA-Z0-9_]{1,19}):(\w+):(\d+):([\dU]+):([\dU]+)/)
{
  # Variables
  my $dsName      = $1;
  my $dsType      = $2;
  my $dsHeartBeat = $3;
  my $dsMin       = $4;
  my $dsMax       = $5;

  # Sanity Checks
  no warnings;
  die "Bad DS Definition, min &gt; max: $options{'ds'}\n" if $dsMin &gt; $dsMax;
  use warnings;

  if ( $dsType ne "GAUGE"
       and $dsType ne "COUNTER"
       and $dsType ne "DERIVE"
       and $dsType ne "ABSOLUTE" )
  {
    die "Bad DS Definition, unknown DS type: $options{'ds'}\n";
  }
}
else
{
  die "Bad DS Definition: $options{'ds'}\n";
}
# +----------------------------------------------------------------------------+
# + }}} Validate Options
# +----------------------------------------------------------------------------+

# +----------------------------------------------------------------------------+
# + {{{ Parse XML &amp; add DS
# +----------------------------------------------------------------------------+
# Datasource
if ( $options{'ds'} =~ /^DS:([a-zA-Z0-9_]{1,19}):(\w+):(\d+):([\dU]+):([\dU]+)/)
{
  # Variables
  my $dsName      = $1;
  my $dsType      = $2;
  my $dsHeartBeat = $3;
  my $dsMin       = $4;
  my $dsMax       = $5;

  # Get XML Output
  if ( my $xml = `rrdtool dump $options{'source'}` )
  {

	$xml=addDSToRRD($dsName,$dsType,$dsHeartBeat,$dsMin,$dsMax,$xml);

    # Move the old source
    rename($options{'source'}, $options{'source'} . ".bak") or
      die "Could not move $options{'source'} to $options{'source'}.bak";

    # Write output
    open(OUTF, "&gt;$options{'source'}.xml") or
      die "Could not open $options{'source'}.xml for writing";
    print OUTF $xml;
    close(OUTF);

    # Re-import
	print "Restore...\n";
    `rrdtool restore $options{'source'}.xml $options{'source'}` ;
  }
  else
  {
    die "Could not dump: $!\n";
  }
}
# +----------------------------------------------------------------------------+
# + }}} Parse XML &amp; add DS
# +----------------------------------------------------------------------------+

sub addDSToRRD{
	my ($dsName,$dsType,$dsHeartBeat,$dsMin,$dsMax,$xml) =@_;
	my $line;	
	my $outXML="";
	foreach $line (split(/\n/,$xml)) {
		if ( $line=~ /Round Robin Archives/ ){
			$outXML=$outXML."	&lt;ds&gt;
		&lt;name&gt; $dsName &lt;/name&gt;
		&lt;type&gt; $dsType &lt;/type&gt;
		&lt;minimal_heartbeat&gt; $dsHeartBeat &lt;/minimal_heartbeat&gt;
		&lt;min&gt; $dsMin &lt;/min&gt;
		&lt;max&gt; $dsMax &lt;/max&gt;
		
		&lt;!-- PDP Status --&gt;
		&lt;last_ds&gt; UNKN &lt;/last_ds&gt;
		&lt;value&gt; 0.0000000000e+00 &lt;/value&gt;
		&lt;unknown_sec&gt; 0 &lt;/unknown_sec&gt;
	&lt;/ds&gt;\n".$line."\n";	
		}elsif ($line =~ /^(.+?&lt;row&gt;)(.+?)(&lt;\/row&gt;.*)$/){
			my @datasources_in_entry = split(/&lt;\/v&gt;/, $2);
			splice(@datasources_in_entry, 999, 0, "&lt;v&gt; 0 ");
			my $new_line = join("&lt;/v&gt;", @datasources_in_entry);
			$outXML=$outXML."$1$new_line&lt;/v&gt;$3\n";
		}elsif ($line =~ /&lt;\/cdp_prep&gt;/){
			$outXML=$outXML."
		 &lt;ds&gt;&lt;value&gt; NaN &lt;/value&gt;  &lt;unknown_datapoints&gt; 0 &lt;/unknown_datapoints&gt;&lt;/ds&gt;\n".$line."\n";			
		}else{
			$outXML=$outXML.$line."\n";	
		}
	}
	
	return $outXML;
}

# +----------------------------------------------------------------------------+
# + {{{ POD
# +----------------------------------------------------------------------------+
__END__

=head1 NAME

add_ds.pl - Add datasource to an existing RRD

=head1 SYNOPSIS

add_ds.pl [options] --source="source.rrd" --ds="DS:new:GAUGE:600:U:U"

 Options:
   --help            brief help message
   --man             full documentation
   --verbose         describe what is happening
   --nobackup        do not create a .rrd.bak file

=head1 OPTIONS

=over 8

=item B&lt;--help&gt;

Print a brief help message and exits.

=item B&lt;--man&gt;

Prints the manual page and exits.

=back

=head1 DESCRIPTION

B&lt;This program&gt; will backup an existing rrd and add a new datasource.

=cut
# +----------------------------------------------------------------------------+
# + }}} POD
# +----------------------------------------------------------------------------+
</pre></body></html>