1#!@PERL@
2#  Copyright (C) 2002  Stanislav Sinyagin
3#
4#  This program is free software; you can redistribute it and/or modify
5#  it under the terms of the GNU General Public License as published by
6#  the Free Software Foundation; either version 2 of the License, or
7#  (at your option) any later version.
8#
9#  This program is distributed in the hope that it will be useful,
10#  but WITHOUT ANY WARRANTY; without even the implied warranty of
11#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12#  GNU General Public License for more details.
13#
14#  You should have received a copy of the GNU General Public License
15#  along with this program; if not, write to the Free Software
16#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17
18# Stanislav Sinyagin <ssinyagin@k-open.com>
19
20# Generate the SNMP discovery instructions XML file out of plaintext
21# list of hosts.
22
23use strict;
24use warnings;
25BEGIN { require '@devdiscover_config_pl@'; }
26
27use Getopt::Long;
28use XML::LibXML;
29use IO::File;
30
31use Torrus::Log;
32
33our $outFormatVersion = '1.0';
34
35our @hosts = ();
36our $hostfile;
37
38our %globalParams =
39    (
40     'output-file'         => 'routers.xml',
41     'domain-name'         => '',
42     'host-subtree'        => '/Routers',
43     'snmp-port'           => '161',
44     'snmp-community'      => 'public',
45     'snmp-version'        => '2c',
46     'snmp-timeout'        => 10,
47     'snmp-retries'        => 2,
48     'rrd-hwpredict'       => 0,
49     'data-dir'            => '@defrrddir@',
50     );
51
52our $outfile = 'routers.ddx';
53
54
55my $creator = "Torrus version @VERSION@\n" .
56    "This file was generated by command:\n" .
57    $0 . " \\\n";
58foreach my $arg ( @ARGV )
59{
60    if( $arg =~ /^--/ )
61    {
62        $creator .= ' ' . $arg . ' ';
63    }
64    else
65    {
66        $creator .= "\'" . $arg . "\'\\\n";
67    }
68}
69$creator .= "\nOn " . scalar(localtime(time));
70
71my $ok = GetOptions(
72                    'host=s'      => \@hosts,
73                    'hostfile=s'  => \$hostfile,
74                    'out=s'       => \$outfile,
75                    'discout=s'   => \$globalParams{'output-file'},
76                    'domain=s'    => \$globalParams{'domain-name'},
77                    'version=s'   => \$globalParams{'snmp-version'},
78                    'community=s' => \$globalParams{'snmp-community'},
79                    'port=i'      => \$globalParams{'snmp-port'},
80                    'timeout=i'   => \$globalParams{'snmp-timeout'},
81                    'retries=i'   => \$globalParams{'snmp-retries'},
82                    'subtree=s'   => \$globalParams{'host-subtree'},
83                    'holtwinters' => \$globalParams{'rrd-hwpredict'},
84                    'datadir=s'   => \$globalParams{'data-dir'},
85                    );
86
87if( not $ok or
88    ( not $hostfile and scalar(@hosts) == 0 ) or
89    scalar( @ARGV ) > 0 )
90{
91    print STDERR "Generate devdiscover XML configuration\n";
92
93    print STDERR "Usage: $0 options...\n",
94    "Options:\n",
95    " --host=hostname         device hostname\n",
96    " --hostfile=filename     space-separated device hostnames file\n",
97    " --out=filename          output file             [".$outfile."]\n",
98
99    " --discout=filename      discovery output file\n",
100    "      [", $globalParams{'output-file'}, "]\n",
101
102    " --domain=domain         optional DNS domain name\n",
103
104    " --version=v             SNMP version         [",
105    $globalParams{'snmp-version'}, "]\n",
106
107    " --community=string      SNMP read community  [",
108    $globalParams{'snmp-community'}, "]\n",
109
110    " --port=number           SNMP port            [",
111    $globalParams{'snmp-port'}, "]\n",
112
113    " --retries=number        SNMP retries         [",
114    $globalParams{'snmp-retries'}, "]\n",
115
116    " --timeout=number        SNMP timeout         [",
117    $globalParams{'snmp-timeout'}, "]\n",
118
119    " --subtree=string        Subtree name         [",
120    $globalParams{'host-subtree'}, "]\n",
121
122    " --datadir=path          data-dir parameter   [",
123    $globalParams{'data-dir'}, "]\n",
124
125    " --holtwinters           Enable Holt-Winters analysis\n",
126    "\n",
127    "Host names may be of form \"host:devname\" where devname is a symbolic\n",
128    "device name.\n",
129    "Output file is placed into " . $Torrus::Global::discoveryDir,
130    "\n if no path is given.\n";
131    exit 1;
132}
133
134# Place the output file in discovery directory if the path is not given
135if( $outfile !~ /\// )
136{
137    $outfile = $Torrus::Global::discoveryDir . '/' . $outfile;
138}
139
140# Convert flags from true/false to yes/no
141foreach my $param ( 'rrd-hwpredict' )
142{
143    if( $globalParams{$param} )
144    {
145        $globalParams{$param} = 'yes';
146    }
147    else
148    {
149        $globalParams{$param} = 'no';
150    }
151}
152
153if( $globalParams{'host-subtree'} !~ /^\/[0-9A-Za-z_\-\.\/]*$/ or
154    $globalParams{'host-subtree'} =~ /\.\./ )
155{
156    Error("Invalid format for subtree name: " . $globalParams{'host-subtree'});
157    exit 1;
158}
159
160if( defined $hostfile )
161{
162    my $fh = IO::File->new($hostfile, 'r');
163    if( not defined($fh) )
164    {
165        print STDERR "Cannot open $hostfile: $!";
166        exit 1;
167    }
168    while(<$fh>)
169    {
170        s/^\s+//;
171        s/\s+$//;
172        push( @hosts, split( /\s+/ ) );
173    }
174    $fh->close()
175}
176
177# Create XML DOM
178
179my $doc = XML::LibXML->createDocument( "1.0", "UTF-8" );
180my $root = $doc->createElement('snmp-discovery');
181$doc->setDocumentElement( $root );
182
183{
184    my $fileInfoNode = $doc->createElement('file-info');
185    $root->appendChild( $fileInfoNode );
186
187    my $formatNode = $doc->createElement('format-version');
188    $formatNode->appendText( $outFormatVersion );
189    $fileInfoNode->appendChild( $formatNode );
190}
191
192{
193    my $creatorNode = $doc->createElement('creator-info');
194    $creatorNode->appendText( $creator );
195    $root->appendChild( $creatorNode );
196}
197
198createParamsDom( \%globalParams, $doc, $root );
199
200
201foreach my $host ( @hosts )
202{
203    my $devname = $host;
204    if( $host =~ /([^:]+):(.+)/ )
205    {
206        $host = $1;
207        $devname = $2;
208    }
209
210    my $hostNode = $doc->createElement('host');
211    $root->appendChild( $hostNode );
212
213    my %hostParams = ( 'snmp-host'      => $host );
214    if( $devname ne $host )
215    {
216        $hostParams{'symbolic-name'} = $devname;
217    }
218
219    createParamsDom( \%hostParams, $doc, $hostNode );
220}
221
222$ok = $doc->toFile( $outfile, 2 );
223if( $ok )
224{
225    print STDERR ("Wrote $outfile\n");
226}
227else
228{
229    print STDERR ("Cannot write $outfile: $!\n");
230}
231
232
233exit($ok ? 0:1);
234
235
236sub createParamsDom
237{
238    my $params = shift;
239    my $document = shift;
240    my $parentNode = shift;
241
242    foreach my $param ( sort keys %{$params} )
243    {
244        my $paramNode = $document->createElement('param');
245        $paramNode->setAttribute( 'name', $param );
246        $paramNode->setAttribute( 'value', $params->{$param} );
247        $parentNode->appendChild( $paramNode );
248    }
249    return;
250}
251
252
253
254
255# Local Variables:
256# mode: perl
257# indent-tabs-mode: nil
258# perl-indent-level: 4
259# End:
260