#!/usr/bin/perl
#  Copyright (C) 2002  Stanislav Sinyagin
#
#  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.

# Stanislav Sinyagin <ssinyagin@k-open.com>

# Generate the SNMP discovery instructions XML file out of plaintext
# list of hosts.

use strict;
use warnings;
BEGIN { require '/usr/share/torrus/conf_defaults/devdiscover-config.pl'; }

use Getopt::Long;
use XML::LibXML;
use IO::File;

use Torrus::Log;

our $outFormatVersion = '1.0';

our @hosts = ();
our $hostfile;

our %globalParams =
    (
     'output-file'         => 'routers.xml',
     'domain-name'         => '',
     'host-subtree'        => '/Routers',
     'snmp-port'           => '161',
     'snmp-community'      => 'public',
     'snmp-version'        => '2c',
     'snmp-timeout'        => 10,
     'snmp-retries'        => 2,
     'rrd-hwpredict'       => 0,
     'data-dir'            => '/var/lib/torrus/collector_rrd',
     );

our $outfile = 'routers.ddx';


my $creator = "Torrus version 3.00\n" .
    "This file was generated by command:\n" .
    $0 . " \\\n";
foreach my $arg ( @ARGV )
{
    if( $arg =~ /^--/ )
    {
        $creator .= ' ' . $arg . ' ';
    }
    else
    {
        $creator .= "\'" . $arg . "\'\\\n";
    }
}
$creator .= "\nOn " . scalar(localtime(time));

my $ok = GetOptions(
                    'host=s'      => \@hosts,
                    'hostfile=s'  => \$hostfile,
                    'out=s'       => \$outfile,
                    'discout=s'   => \$globalParams{'output-file'},
                    'domain=s'    => \$globalParams{'domain-name'},
                    'version=s'   => \$globalParams{'snmp-version'},
                    'community=s' => \$globalParams{'snmp-community'},
                    'port=i'      => \$globalParams{'snmp-port'},
                    'timeout=i'   => \$globalParams{'snmp-timeout'},
                    'retries=i'   => \$globalParams{'snmp-retries'},
                    'subtree=s'   => \$globalParams{'host-subtree'},
                    'holtwinters' => \$globalParams{'rrd-hwpredict'},
                    'datadir=s'   => \$globalParams{'data-dir'},
                    );

if( not $ok or
    ( not $hostfile and scalar(@hosts) == 0 ) or
    scalar( @ARGV ) > 0 )
{
    print STDERR "Generate devdiscover XML configuration\n";

    print STDERR "Usage: $0 options...\n",
    "Options:\n",
    " --host=hostname         device hostname\n",
    " --hostfile=filename     space-separated device hostnames file\n",
    " --out=filename          output file             [".$outfile."]\n",

    " --discout=filename      discovery output file\n",
    "      [", $globalParams{'output-file'}, "]\n",

    " --domain=domain         optional DNS domain name\n",

    " --version=v             SNMP version         [",
    $globalParams{'snmp-version'}, "]\n",

    " --community=string      SNMP read community  [",
    $globalParams{'snmp-community'}, "]\n",

    " --port=number           SNMP port            [",
    $globalParams{'snmp-port'}, "]\n",

    " --retries=number        SNMP retries         [",
    $globalParams{'snmp-retries'}, "]\n",

    " --timeout=number        SNMP timeout         [",
    $globalParams{'snmp-timeout'}, "]\n",

    " --subtree=string        Subtree name         [",
    $globalParams{'host-subtree'}, "]\n",

    " --datadir=path          data-dir parameter   [",
    $globalParams{'data-dir'}, "]\n",

    " --holtwinters           Enable Holt-Winters analysis\n",
    "\n",
    "Host names may be of form \"host:devname\" where devname is a symbolic\n",
    "device name.\n",
    "Output file is placed into " . $Torrus::Global::discoveryDir,
    "\n if no path is given.\n";
    exit 1;
}

# Place the output file in discovery directory if the path is not given
if( $outfile !~ /\// )
{
    $outfile = $Torrus::Global::discoveryDir . '/' . $outfile;
}

# Convert flags from true/false to yes/no
foreach my $param ( 'rrd-hwpredict' )
{
    if( $globalParams{$param} )
    {
        $globalParams{$param} = 'yes';
    }
    else
    {
        $globalParams{$param} = 'no';
    }
}

if( $globalParams{'host-subtree'} !~ /^\/[0-9A-Za-z_\-\.\/]*$/ or
    $globalParams{'host-subtree'} =~ /\.\./ )
{
    Error("Invalid format for subtree name: " . $globalParams{'host-subtree'});
    exit 1;
}

if( defined $hostfile )
{
    my $fh = IO::File->new($hostfile, 'r');
    if( not defined($fh) )
    {
        print STDERR "Cannot open $hostfile: $!";
        exit 1;
    }
    while(<$fh>)
    {
        s/^\s+//;
        s/\s+$//;
        push( @hosts, split( /\s+/ ) );
    }
    $fh->close()
}

# Create XML DOM

my $doc = XML::LibXML->createDocument( "1.0", "UTF-8" );
my $root = $doc->createElement('snmp-discovery');
$doc->setDocumentElement( $root );

{
    my $fileInfoNode = $doc->createElement('file-info');
    $root->appendChild( $fileInfoNode );

    my $formatNode = $doc->createElement('format-version');
    $formatNode->appendText( $outFormatVersion );
    $fileInfoNode->appendChild( $formatNode );
}

{
    my $creatorNode = $doc->createElement('creator-info');
    $creatorNode->appendText( $creator );
    $root->appendChild( $creatorNode );
}

createParamsDom( \%globalParams, $doc, $root );


foreach my $host ( @hosts )
{
    my $devname = $host;
    if( $host =~ /([^:]+):(.+)/ )
    {
        $host = $1;
        $devname = $2;
    }

    my $hostNode = $doc->createElement('host');
    $root->appendChild( $hostNode );

    my %hostParams = ( 'snmp-host'      => $host );
    if( $devname ne $host )
    {
        $hostParams{'symbolic-name'} = $devname;
    }

    createParamsDom( \%hostParams, $doc, $hostNode );
}

$ok = $doc->toFile( $outfile, 2 );
if( $ok )
{
    print STDERR ("Wrote $outfile\n");
}
else
{
    print STDERR ("Cannot write $outfile: $!\n");
}


exit($ok ? 0:1);


sub createParamsDom
{
    my $params = shift;
    my $document = shift;
    my $parentNode = shift;

    foreach my $param ( sort keys %{$params} )
    {
        my $paramNode = $document->createElement('param');
        $paramNode->setAttribute( 'name', $param );
        $paramNode->setAttribute( 'value', $params->{$param} );
        $parentNode->appendChild( $paramNode );
    }
    return;
}




# Local Variables:
# mode: perl
# indent-tabs-mode: nil
# perl-indent-level: 4
# End:
