#!/usr/local/bin/perl # argus-rename v2011121001 # Rename objects being monitored by Argus # without losing all your graph data and stats # Copyright 2011 Jeremy Kister # Released under Perl's Artistic License # # todo: combine group/parent stats, maybe? # fix bugs! - prog is beta use strict; use Getopt::Std; my %opt; # D debug # o old object name # n new object name # a location of argus-config # t test only (no file moving) # e my %dir; BEGIN { getopts('Do:n:a:t', \%opt); if( $opt{a} ){ $ENV{PATH} .= ':' . $opt{a}; } open(AC, "argus-config --datadir --libdir --bindir |") || die "cannot find argus-config in your path or -a directory.\n"; for my $el (qw/data lib bin/){ chop($dir{$el}=); } close AC; unshift @INC, $dir{lib}; }; use Argus::Ctl; use Argus::Encode; use Argus::HashDir; syntax() unless $opt{o} && $opt{n}; die "object not under Top?\n" unless( $opt{o} =~ /^Top:\S/ && $opt{n} =~ /^Top:\S/ ); my %c; my @objs = children($opt{o}); push @objs, $opt{o}; # self for my $obj (@objs) { debug( "object: [$obj]" ); my $new = $obj; $new =~ s/^$opt{o}/$opt{n}/; # QQQ must also change object name # e.g., rename -o Top:SBCs:26nyc:sbc1 -n Top:SBC:nyc0:4250:sbc1 # stats/X/D/Top:SBCs:26nyc:sbc1:sd1:Network:public:Errors:SNMP_.1.3.6.1.2.1.2.2.1.20_public_sbc1-sd1.26nyc # -> stats/J/S/Top:SBC:26nyc:sbc1:sd1:Network:public:Errors:SNMP_.1.3.6.1.2.1.2.2.1.20_public_sbc1-sd1.26nyc # vs # -> stats/J/S/Top:SBC:nyc0:4250:sbc1:sd1:Network:public:Errors:SNMP_.1.3.6.1.2.1.2.2.1.20_public_sd1-4250-1.nyc0 my %encode = ( old => encode($obj), new => encode($new) ); my %hash = ( old => hashed_directory($encode{old}), new => hashed_directory($encode{new}) ); die "no object found for $obj\n" unless(-f "$dir{data}/stats/$hash{old}/$encode{old}"); debug( "** RENAME: $obj -> $new" ); for my $sdir (qw/stats html gdata/){ my $o = "$dir{data}/$sdir/$hash{old}/$encode{old}"; my $n = "$dir{data}/$sdir/$hash{new}/$encode{new}"; if( $sdir eq 'html' ){ # not .top, etc $o .= '.base'; $n .= '.base'; } if( -f $o ){ debug( " $sdir/$hash{old}/$encode{old} -> $sdir/$hash{new}/$encode{new}" ); unless( $opt{t} ){ rename( $o, $n ) || die "could not rename $o -> $n: $!\n"; } } } for my $set (qw/samples hours days/){ for my $size (qw/thumb full/){ my $o = "$dir{data}/gcache/$encode{old}.$set.$size.png"; my $n = "$dir{data}/gcache/$encode{new}.$set.$size.png"; if( -f $o ){ debug( " gcache/$encode{old}.$set.$size.png -> gcache/$encode{new}.$set.$size.png" ); unless( $opt{t} ){ rename( $o, $n ) || die "could not rename $o -> $n: $!\n"; } } } } } sub children { my $object = shift; my $r = shift || 0; # one connection per child level my $a = Argus::Ctl->new( "$dir{data}/control", who => 'argus-rename', retry => 0, encode => 1, ); die "cannot connect to argus control socket\n" unless( $a && $a->connectedp() ); debug( "[$r] sending children request: $object" ); $a->command_raw( ( func => 'children', object => $object ), ); while( $_ = $a->nextline() ){ if( /^Top:/ ){ chop; debug( "saving: [$_]" ); $c{$_} = 1; debug( "grandchild request: $_" ); my $n = $r + 1; my %g = map { $_ => 1 } children($_,$n); $c{ keys %g } = values %g; }else{ if( $r ){ return 1; }else{ last; } } } delete $c{1}; return (keys %c); } sub syntax { print <<__EOS__ argus-rename v2011120901 rename argus objects without losing historical statistics and graphs usage: argus-rename -o -n modify config file(s) argusctl hup hint: object name is displayed in upper left of arguscgi webpage syntax: argus-rename [-D] [-a ] [-t] -o -n -D print debugging information -o old object name -n new object name -a path to 'argus-config' program -t test mode (no file changes) __EOS__ ; exit; } sub verbose { my $msg = join('', @_); warn "$msg\n"; } sub debug { verbose(@_) if $opt{D}; }