Script to export snmpwalks as zabbix-items.
#!/usr/bin/perl #################################### # # zload_snmpwalk # Version 1.1 # Author: Steven Dossett # Dennis Ploeger # Email: sd at panath.com # develop at dieploegers.de # #################################### # Disclaimer: # This script has only been used with ZABBIX 1.1alpha6. It isn't thoroughly # tested. It isn't very efficient. It may eat your database or cause other # unintentional harm. Be careful and use at your own risk. # Please share bug fixes and improvements that you make... # # The XML-part has been tested with ZABBIX 1.4.2. I don't know, if it works # from the beginning of 1.4 # # See usage instructions by running: zload_snmpwalk -h # # Description: # Creating new ZABBIX host templates can be time consuming. This script # automates some of the process by loading snmpwalk data into a ZABBIX # template. It is very important to use a MIB so that keys and descriptions # for the data are usable. MIBs can be specified on the command line or # snmpwalk may find them via your MIBS environment variable. The template # items will need modification from the ZABBIX UI after bulk loading. The # script doesn't attempt to manage interesting things like 'units' or 'custom # multipliers'. The script also has a limited notion of what qualifies as # 'Character' data and defaults to 'Numeric' for just about everything. # Update the script to properly identify more types. # # An example session (prior 1.4) might work like the following: # # 1 - Create a new host template in the Zabbix UI. Make note of the ID for the # new template. # 2 - Use an additional -T option to test the examples in 2a and 2b. # 2a - Build an initial set of items for the template. In the example below # the template id 10015 is used: # zload_snmpwalk -m SOMEVENDOR-MASTER-MIB secretstring dbuser dbpass 10015 somehost .iso.org.dod.internet.private # 2b - Alternatively, the template can be created from saved snmpwalk data: # zload_snmpwalk -m SOMEVENDOR-MASTER-MIB secretstring dbuser dbpass 10015 somefile # For the option above, the data must be in 'snmpwalk -Of' format. # 3 - Next, the template should be tweaked and tested from the Zabbix UI before # applying to hosts. # # For Zabbix 1.4 use the following workflow: # # 1 - Create a new host template and note the name. # 2 - Run the script with the -x Option to output XML # 3 - Check, if the XML looks valid and remove items you don't want to import # 4 - Switch over to the WEB ui and use the XML importer to import the file # use Getopt::Std; use DBI; use strict; use vars qw($PROG $VERSION $community $host $mib $usagetxt %OPTS $dbhost $dbuser $dbpass $zabbix_db $zabbix_id $translate $dbh $zabbix_port $zabbix_delay $zabbix_history $zabbix_trends $TEST $mode $debug $zabbix_right $zabbix_type); $VERSION = "1.0"; $PROG = "zload_snmpwalk"; $usagetxt = qq { USAGE: $PROG [OPTIONS] <community> <zabbix_id> <agent> <oid> $PROG [OPTIONS] <community> <zabbix_id> <file> Version: $VERSION snmpwalk the target <agent> from the starting <oid> and then store the results in the ZABBIX template <zabbix_id>. Alternatively, a <file> containing the output of a previous snmpwalk can be used. The data is expected in the format generated by 'smpwalk -Of' and should be generated using the appropriate MIB(s) so that meaningful descriptions can be created for ZABBIX. Without using a MIB, the attempt will likely fail as the descriptions used for ZABBIX keys will be duplicated. Be sure to test your data with the -T option first! For Zabbix > 1.4 a XML-output suitable for importing over the WEB frontend is supported (-x). To use it, specify the hosts name rather than the hosts id as <zabbix_id>. BASIC ENVIRONMENT REQUIREMENTS: Zabbix 1.1alpha6 - Not tested with any other versions. perl - Tested with 5.8.0 Mysql & perl DBI - Might work with postgres after minor changes. net-snmp - Tested with net-snmp 5.0.8 PRIMARY ARGUMENTS: <community> SNMP community string <dbuser> DB user that can update ZABBIX tables <dbpasswd> DB password for the user <zabbix_id> Zabbix template id for a template created from the UI DATA SOURCES: <agent> Target SNMP host/agent <oid> Beginning oid - example: .iso.org.dod.internet.private OR <file> File containing snmpwalk data in '-Of' format to be loaded OPTIONS: -T Test Mode. No DB updates - just view the new records. -v 1|2c|3 SNMP version -m MIB[:...] load given list of MIBs (ALL loads everything) -p port SNMP port, default is 161 -x Output XML suitable for import rather than doing SQL. -D Output debugging information Database or ZABBIX data related options: -r delay SNMP polling delay, default is 60 -h history How long to keep polling history, default is 7 -t trends How long to keep polling trends, default is 365 -s server Database server, default is localhost -R num Use num indexes from the right as the description (default: 2) -d database Database, default is zabbix -u user Database-user -P password Database-password }; sub connect_db { my $db = "DBI:mysql:$zabbix_db:$dbhost"; $dbh = DBI->connect($db, $dbuser, $dbpass) || die "Can't connect to DB: $dbh->errstr\n"; $dbh->{AutoCommit} = 0; } sub get_zabbix_description { my $raw_oid = shift(@_); my $pos; # Step back 2 positions for a description string and key $pos = length($raw_oid); for (my $i=0; $i<$zabbix_right;$i++) { $pos = rindex($raw_oid,'.', $pos - 1); } return substr($raw_oid, $pos + 1); } sub get_zabbix_oid { my $raw_oid = shift(@_); my $zabbix_oid = `$translate $raw_oid`; chomp($zabbix_oid); return $zabbix_oid; } sub get_zabbix_value_type { my $snmp_type = shift(@_); my $zabbix_value_type; # Zabbix types # 0 = Numeric # 1 = Character # Add additional character types as needed. More are needed.. SWITCH: { if ($snmp_type eq "STRING") { $zabbix_value_type = 1; last SWITCH; } $zabbix_value_type = 0; } return $zabbix_value_type; } sub usage { print $usagetxt; exit 0; } MAIN: $| = 1; # no print delay my $input; my $sql; my $tcounter = 0; if (!getopts('d:h:m:p:r:s:t:u:v:Txu:P:R:D', \%OPTS)) { usage(); } if (@ARGV == 3 || @ARGV == 4) { $TEST = exists($OPTS{T}) ? "1" : "0"; $community = $ARGV[0]; $dbuser = exists($OPTS{u}) ? ($OPTS{u}) : ""; $dbpass = exists($OPTS{P}) ? ($OPTS{P}) : ""; $zabbix_id = $ARGV[1]; $dbhost = exists($OPTS{s}) ? ($OPTS{s}) : "localhost"; $zabbix_db = exists($OPTS{d}) ? ($OPTS{d}) : "zabbix"; $zabbix_port = exists($OPTS{p}) ? ($OPTS{p}) : "161"; $zabbix_delay = exists($OPTS{r}) ? ($OPTS{r}) : "60"; $zabbix_history = exists($OPTS{h}) ? ($OPTS{h}) : "7"; $zabbix_trends = exists($OPTS{t}) ? ($OPTS{t}) : "365"; $translate = "snmptranslate -Ofn "; $translate .= exists($OPTS{m}) ? ("-m $OPTS{m} ") : ""; $mode = exists($OPTS{x}) ? 'xml' : 'sql'; $debug = exists($OPTS{D}) ? 1 : 0; $zabbix_right = exists($OPTS{R}) ? ($OPTS{R}) : 2; # Input from file by default, might change below $input = "<$ARGV[2]"; } else { usage(); }; if ($OPTS{v} eq "1") { $zabbix_type = 1; } elsif ($OPTS{v} eq "2c") { $zabbix_type = 4; } elsif ($OPTS{v} eq "3") { $zabbix_type = 6; } # Data from live snmpwalk if (@ARGV == 4) { $host = $ARGV[2]; $input = "snmpwalk -c $community "; $input .= exists($OPTS{m}) ? ("-m $OPTS{m} ") : ""; $input .= exists($OPTS{v}) ? ("-v $OPTS{v} ") : ""; # Host $input .= "-Of $host"; $input .= exists($OPTS{p}) ? (":$OPTS{p} ") : ":161 "; # OID $input .= "$ARGV[3]|"; } if ($mode eq "sql") { connect_db(); $sql = $dbh->prepare("INSERT INTO items (type, snmp_community, snmp_oid, snmp_port, hostid, description, key_, delay, history, trends, value_type) VALUES (?,?,?,?,?,?,?,?,?,?,?)"); } else { my $date = `date +%d.%m.%y`; my $time = `date +%H:%M`; chop($date); chop($time); print '<zabbix_export version="1.0" date="'.$date.'" time="'.$time.'">'."\n"; print "\t<hosts>\n"; print "\t\t".'<host name="'.$zabbix_id.'">'."\n"; print "\t\t\t<status>3</status>\n"; } open(SWALK,$input) or die "Can't open $input\n"; if ($debug) { print "Processing Data from $input "; } while(my $line = <SWALK>) { my $zabbix_value_type; my $zabbix_description; my $zabbix_oid; next if ($line !~ /(.iso.org.dod.*) = (.*):/ ); #$1 = oid string to translate #$2 = integer, string or other snmp type #More snmp "character" types should be added $zabbix_description = get_zabbix_description($1); $zabbix_oid = get_zabbix_oid($1); $zabbix_value_type = get_zabbix_value_type($2); if ($TEST) { if (($tcounter++ % 10) == 0) { print "\ntype\tsnmp_community\tsnmp_oid\tsnmp_port\t", "hostid\tdescription\tkey_\tdelay\t", "history\ttrends\tvalue_type\n"; } print "$zabbix_type\t$community\t$zabbix_oid\t$zabbix_port\t", "$zabbix_id\t$zabbix_description\t", "$zabbix_description\t$zabbix_delay\t", "$zabbix_history\t$zabbix_trends\t", "$zabbix_value_type\n"; } elsif ($mode eq 'sql') { print "." if (($tcounter++ % 10) == 0 ); $sql->execute($zabbix_type, $community, $zabbix_oid, $zabbix_port, $zabbix_id, $zabbix_description, $zabbix_description, $zabbix_delay, $zabbix_history, $zabbix_trends, $zabbix_value_type) || die "Insert Failure: $sql->strerror\n"; } else { # Output XML print "\t\t\t".'<item type="'.$zabbix_type.'" key="'.$zabbix_description.'" value_type="'.$zabbix_value_type.'">'."\n"; print "\t\t\t\t<description>$zabbix_description</description>\n"; print "\t\t\t\t<delay>$zabbix_delay</delay>\n"; print "\t\t\t\t<history>$zabbix_history</history>\n"; print "\t\t\t\t<trends>$zabbix_trends</trends>\n"; print "\t\t\t\t<snmp_community>$community</snmp_community>\n"; print "\t\t\t\t<snmp_oid>$zabbix_oid</snmp_oid>\n"; print "\t\t\t\t<snmp_port>$zabbix_port</snmp_port>\n"; print "\t\t\t</item>\n"; } } close(SWALK); if ($mode eq "sql") { $dbh->commit(); $dbh->disconnect(); } else { print "\t\t</host>\n"; print "\t</hosts>\n"; print "</zabbix_export>\n"; } if ($debug) { print "Finished\n"; } exit 0;
Discussion
Hi! Just want to let you know that this script do NOT include groups> and <group> tags to the result xml file, so please pay attention to it, imported host/template will be added to the group “Imported hosts” by default. Also in the generated by this script xml file there are NO <items> </items> tags, as a result items will be NOT imported, you need to add them on your own.
Here is an updated version with <group>Templates</group> and <items>. Useful support for v3 is still missing (it always uses community to query remote device), but I added the related xml tags:
#!/usr/bin/perl #################################### # # zload_snmpwalk # Version 1.1a # Author: Steven Dossett # Dennis Ploeger # Nicola Canepa # Email: sd at panath.com # develop at dieploegers.de # nicola.canepa.74 at gmail.com # #################################### # Disclaimer: # This script has only been used with ZABBIX 1.1alpha6. It isn't thoroughly # tested. It isn't very efficient. It may eat your database or cause other # unintentional harm. Be careful and use at your own risk. # Please share bug fixes and improvements that you make... # # The XML-part has been tested with ZABBIX 1.4.2. I don't know, if it works # from the beginning of 1.4 # # See usage instructions by running: zload_snmpwalk -h # # Description: # Creating new ZABBIX host templates can be time consuming. This script # automates some of the process by loading snmpwalk data into a ZABBIX # template. It is very important to use a MIB so that keys and descriptions # for the data are usable. MIBs can be specified on the command line or # snmpwalk may find them via your MIBS environment variable. The template # items will need modification from the ZABBIX UI after bulk loading. The # script doesn't attempt to manage interesting things like 'units' or 'custom # multipliers'. The script also has a limited notion of what qualifies as # 'Character' data and defaults to 'Numeric' for just about everything. # Update the script to properly identify more types. # # An example session (prior 1.4) might work like the following: # # 1 - Create a new host template in the Zabbix UI. Make note of the ID for the # new template. # 2 - Use an additional -T option to test the examples in 2a and 2b. # 2a - Build an initial set of items for the template. In the example below # the template id 10015 is used: # zload_snmpwalk -m SOMEVENDOR-MASTER-MIB secretstring dbuser dbpass 10015 somehost .iso.org.dod.internet.private # 2b - Alternatively, the template can be created from saved snmpwalk data: # zload_snmpwalk -m SOMEVENDOR-MASTER-MIB secretstring dbuser dbpass 10015 somefile # For the option above, the data must be in 'snmpwalk -Of' format. # 3 - Next, the template should be tweaked and tested from the Zabbix UI before # applying to hosts. # # For Zabbix 1.4 use the following workflow: # # 1 - Create a new host template and note the name. # 2 - Run the script with the -x Option to output XML # 3 - Check, if the XML looks valid and remove items you don't want to import # 4 - Switch over to the WEB ui and use the XML importer to import the file # use Getopt::Std; use DBI; use strict; use vars qw($PROG $VERSION $community $host $mib $usagetxt %OPTS $dbhost $dbuser $dbpass $zabbix_db $zabbix_id $translate $dbh $zabbix_port $zabbix_delay $zabbix_history $zabbix_trends $TEST $mode $debug $zabbix_right $zabbix_type); $VERSION = "1.0"; $PROG = "zload_snmpwalk"; $usagetxt = qq { USAGE: $PROG [OPTIONS] <community> <zabbix_id> <agent> <oid> $PROG [OPTIONS] <community> <zabbix_id> <file> Version: $VERSION snmpwalk the target <agent> from the starting <oid> and then store the results in the ZABBIX template <zabbix_id>. Alternatively, a <file> containing the output of a previous snmpwalk can be used. The data is expected in the format generated by 'smpwalk -Of' and should be generated using the appropriate MIB(s) so that meaningful descriptions can be created for ZABBIX. Without using a MIB, the attempt will likely fail as the descriptions used for ZABBIX keys will be duplicated. Be sure to test your data with the -T option first! For Zabbix > 1.4 a XML-output suitable for importing over the WEB frontend is supported (-x). To use it, specify the hosts name rather than the hosts id as <zabbix_id>. BASIC ENVIRONMENT REQUIREMENTS: Zabbix 1.1alpha6 - Not tested with any other versions. perl - Tested with 5.8.0 Mysql & perl DBI - Might work with postgres after minor changes. net-snmp - Tested with net-snmp 5.0.8 PRIMARY ARGUMENTS: <community> SNMP community string <dbuser> DB user that can update ZABBIX tables <dbpasswd> DB password for the user <zabbix_id> Zabbix template id for a template created from the UI DATA SOURCES: <agent> Target SNMP host/agent <oid> Beginning oid - example: .iso.org.dod.internet.private OR <file> File containing snmpwalk data in '-Of' format to be loaded OPTIONS: -T Test Mode. No DB updates - just view the new records. -v 1|2c|3 SNMP version -m MIB[:...] load given list of MIBs (ALL loads everything) -p port SNMP port, default is 161 -x Output XML suitable for import rather than doing SQL. -D Output debugging information Database or ZABBIX data related options: -r delay SNMP polling delay, default is 60 -h history How long to keep polling history, default is 7 -t trends How long to keep polling trends, default is 365 -s server Database server, default is localhost -R num Use num indexes from the right as the description (default: 2) -d database Database, default is zabbix -u user Database-user -P password Database-password }; sub connect_db { my $db = "DBI:mysql:$zabbix_db:$dbhost"; $dbh = DBI->connect($db, $dbuser, $dbpass) || die "Can't connect to DB: $dbh->errstr\n"; $dbh->{AutoCommit} = 0; } sub get_zabbix_description { my $raw_oid = shift(@_); my $pos; # Step back 2 positions for a description string and key $pos = length($raw_oid); for (my $i=0; $i<$zabbix_right;$i++) { $pos = rindex($raw_oid,'.', $pos - 1); } return substr($raw_oid, $pos + 1); } sub get_zabbix_oid { my $raw_oid = shift(@_); my $zabbix_oid = `$translate $raw_oid`; chomp($zabbix_oid); return $zabbix_oid; } sub get_zabbix_value_type { my $snmp_type = shift(@_); my $zabbix_value_type; # Zabbix types # 0 = Numeric # 1 = Character # Add additional character types as needed. More are needed.. SWITCH: { if ($snmp_type eq "STRING") { $zabbix_value_type = 1; last SWITCH; } $zabbix_value_type = 0; } return $zabbix_value_type; } sub usage { print $usagetxt; exit 0; } MAIN: $| = 1; # no print delay my $input; my $sql; my $tcounter = 0; if (!getopts('d:h:m:p:r:s:t:u:v:Txu:P:R:D', \%OPTS)) { usage(); } if (@ARGV == 3 || @ARGV == 4) { $TEST = exists($OPTS{T}) ? "1" : "0"; $community = $ARGV[0]; $dbuser = exists($OPTS{u}) ? ($OPTS{u}) : ""; $dbpass = exists($OPTS{P}) ? ($OPTS{P}) : ""; $zabbix_id = $ARGV[1]; $dbhost = exists($OPTS{s}) ? ($OPTS{s}) : "localhost"; $zabbix_db = exists($OPTS{d}) ? ($OPTS{d}) : "zabbix"; $zabbix_port = exists($OPTS{p}) ? ($OPTS{p}) : "161"; $zabbix_delay = exists($OPTS{r}) ? ($OPTS{r}) : "60"; $zabbix_history = exists($OPTS{h}) ? ($OPTS{h}) : "7"; $zabbix_trends = exists($OPTS{t}) ? ($OPTS{t}) : "365"; $translate = "snmptranslate -Ofn "; $translate .= exists($OPTS{m}) ? ("-m $OPTS{m} ") : ""; $mode = exists($OPTS{x}) ? 'xml' : 'sql'; $debug = exists($OPTS{D}) ? 1 : 0; $zabbix_right = exists($OPTS{R}) ? ($OPTS{R}) : 2; # Input from file by default, might change below $input = "<$ARGV[2]"; } else { usage(); }; if ($OPTS{v} eq "1") { $zabbix_type = 1; } elsif ($OPTS{v} eq "2c") { $zabbix_type = 4; } elsif ($OPTS{v} eq "3") { $zabbix_type = 6; } # Data from live snmpwalk if (@ARGV == 4) { $host = $ARGV[2]; $input = "snmpwalk -c $community "; $input .= exists($OPTS{m}) ? ("-m $OPTS{m} ") : ""; $input .= exists($OPTS{v}) ? ("-v $OPTS{v} ") : ""; # Host $input .= "-Of $host"; $input .= exists($OPTS{p}) ? (":$OPTS{p} ") : ":161 "; # OID $input .= "$ARGV[3]|"; } if ($mode eq "sql") { connect_db(); $sql = $dbh->prepare("INSERT INTO items (type, snmp_community, snmp_oid, snmp_port, hostid, description, key_, delay, history, trends, value_type) VALUES (?,?,?,?,?,?,?,?,?,?,?)"); } else { my $date = `date +%d.%m.%y`; my $time = `date +%H:%M`; chop($date); chop($time); print '<zabbix_export version="1.0" date="'.$date.'" time="'.$time.'">'."\n"; print "\t<hosts>\n"; print "\t\t".'<host name="'.$zabbix_id.'">'."\n"; print "\t\t\t<status>3</status>\n"; } open(SWALK,$input) or die "Can't open $input\n"; if ($debug) { print "Processing Data from $input "; } while(my $line = <SWALK>) { my $zabbix_value_type; my $zabbix_description; my $zabbix_oid; next if ($line !~ /(.iso.org.dod.*) = (.*):/ ); #$1 = oid string to translate #$2 = integer, string or other snmp type #More snmp "character" types should be added $zabbix_description = get_zabbix_description($1); $zabbix_oid = get_zabbix_oid($1); $zabbix_value_type = get_zabbix_value_type($2); if ($TEST) { if (($tcounter++ % 10) == 0) { print "\ntype\tsnmp_community\tsnmp_oid\tsnmp_port\t", "hostid\tdescription\tkey_\tdelay\t", "history\ttrends\tvalue_type\n"; } print "$zabbix_type\t$community\t$zabbix_oid\t$zabbix_port\t", "$zabbix_id\t$zabbix_description\t", "$zabbix_description\t$zabbix_delay\t", "$zabbix_history\t$zabbix_trends\t", "$zabbix_value_type\n"; } elsif ($mode eq 'sql') { print "." if (($tcounter++ % 10) == 0 ); $sql->execute($zabbix_type, $community, $zabbix_oid, $zabbix_port, $zabbix_id, $zabbix_description, $zabbix_description, $zabbix_delay, $zabbix_history, $zabbix_trends, $zabbix_value_type) || die "Insert Failure: $sql->strerror\n"; } else { # Output XML print "\t\t\t<groups><group>Templates</group></groups>\n"; print "\t\t\t<items>\n"; print "\t\t\t".'<item type="'.$zabbix_type.'" key="'.$zabbix_description.'" value_type="'.$zabbix_value_type.'">'."\n"; print "\t\t\t\t<description>$zabbix_description</description>\n"; print "\t\t\t\t<delay>$zabbix_delay</delay>\n"; print "\t\t\t\t<history>$zabbix_history</history>\n"; print "\t\t\t\t<trends>$zabbix_trends</trends>\n"; print "\t\t\t\t<snmp_community>$community</snmp_community>\n"; print "\t\t\t\t<snmpv3_securityname>$community</snmpv3_securityname>\n"; print "\t\t\t\t<snmpv3_securitylevel>0</snmpv3_securitylevel>\n"; print "\t\t\t\t<snmpv3_authpassphrase></snmpv3_authpassphrase>\n"; print "\t\t\t\t<snmpv3_privpassphrase></snmpv3_privpassphrase>\n"; print "\t\t\t\t<snmp_oid>$zabbix_oid</snmp_oid>\n"; print "\t\t\t\t<snmp_port>$zabbix_port</snmp_port>\n"; print "\t\t\t</item>\n"; print "\t\t\t</items>\n"; } } close(SWALK); if ($mode eq "sql") { $dbh->commit(); $dbh->disconnect(); } else { print "\t\t</host>\n"; print "\t</hosts>\n"; print "</zabbix_export>\n"; } if ($debug) { print "Finished\n"; } exit 0;Feel free to replace the version above with this one, and to remove this post.
Nicola
great job, Thanks -x option (xml template generation) works well with 1.8.2 version but only one little issue: ”-T -x” option generates bad XML