This commit is contained in:
Steven Yu 2016-11-01 07:23:26 +00:00 committed by GitHub
commit 83a84d5c83
2 changed files with 173 additions and 64 deletions

View file

@ -34,6 +34,10 @@ tree in a SNMP MIB file.
-x, --privacy=PROTOCOL privacy protocol (DES|AES) -x, --privacy=PROTOCOL privacy protocol (DES|AES)
-X, --privpass=PASSPHRASE privacy passphrase -X, --privpass=PASSPHRASE privacy passphrase
Zabbix template version
-z, --zabbix_ver=2|3 Zabbix Template Schema Version (default: 3)
Zabbix item configuration Zabbix item configuration
--check-delay=SECONDS check interval in seconds (default: 60) --check-delay=SECONDS check interval in seconds (default: 60)
@ -45,7 +49,7 @@ tree in a SNMP MIB file.
### Requirements ### Requirements
* Zabbix v3+ * Zabbix v2.4, 3+
* Perl v5 * Perl v5
* Pod::Usage * Pod::Usage
* XML::Simple * XML::Simple

View file

@ -3,32 +3,20 @@
=pod =pod
=head1 NAME =head1 NAME
mib2zabbix.pl - SNMP MIB to Zabbix Template mib2zabbix.pl - SNMP MIB to Zabbix Template
=head1 SYNOPSIS =head1 SYNOPSIS
mib2zabbix.pl -o <OID> [OPTIONS]... mib2zabbix.pl -o <OID> [OPTIONS]...
Export loaded SNMP MIB OIDs to Zabbix Template XML Export loaded SNMP MIB OIDs to Zabbix Template XML
-f, --filename=PATH output filename (default: stdout) -f, --filename=PATH output filename (default: stdout)
-N, --name=STRING template name (default: OID label) -N, --name=STRING template name (default: OID label)
-G, --group=STRING template group (default: 'Templates') -G, --group=STRING template group (default: 'Templates')
-e, --enable-items enable all template items (default: disabled) -e, --enable-items enable all template items (default: disabled)
-o, --oid=STRING OID tree root to export -o, --oid=STRING OID tree root to export
-v, --snmpver=1|2|3 SNMP version (default: 2) -v, --snmpver=1|2|3 SNMP version (default: 2)
-p, --port=PORT SNMP UDP port number (default: 161) -p, --port=PORT SNMP UDP port number (default: 161)
SNMP Version 1 or 2c specific SNMP Version 1 or 2c specific
-c, --community=STRING SNMP community string (default: 'public') -c, --community=STRING SNMP community string (default: 'public')
SNMP Version 3 specific SNMP Version 3 specific
-L, --level=LEVEL security level (noAuthNoPriv|authNoPriv|authPriv) -L, --level=LEVEL security level (noAuthNoPriv|authNoPriv|authPriv)
-n, --context=CONTEXT context name -n, --context=CONTEXT context name
-u, --username=USERNAME security name -u, --username=USERNAME security name
@ -37,40 +25,36 @@ SNMP Version 3 specific
-x, --privacy=PROTOCOL privacy protocol (DES|AES) -x, --privacy=PROTOCOL privacy protocol (DES|AES)
-X, --privpass=PASSPHRASE privacy passphrase -X, --privpass=PASSPHRASE privacy passphrase
Zabbix item configuration Zabbix template version
-z, --zabbix_ver=2|3 Zabbix Template Schema Version (default: 3)
Zabbix item configuration
--check-delay=SECONDS check interval in seconds (default: 60) --check-delay=SECONDS check interval in seconds (default: 60)
--disc-delay=SECONDS discovery interval in seconds (default: 3600) --disc-delay=SECONDS discovery interval in seconds (default: 3600)
--history=DAYS history retention in days (default: 7) --history=DAYS history retention in days (default: 7)
--trends=DAYS trends retention in days (default: 365) --trends=DAYS trends retention in days (default: 365)
Help
-h, --help print this message -h, --help print this message
=head1 DESCRIPTION =head1 DESCRIPTION
B<mib2zabbix.pl> will export a loaded MIB tree into a Zabbix Template starting B<mib2zabbix.pl> will export a loaded MIB tree into a Zabbix Template starting
from the OID root specified. from the OID root specified.
Requires: Zabbix v2.4 or 3, Perl v5, Pod::Usage, XML::Simple, Net-SNMP
Requires: Zabbix v3, Perl v5, Pod::Usage, XML::Simple, Net-SNMP
=head1 AUTHOR =head1 AUTHOR
Ryan Armstrong <ryan@cavaliercoder.com> Ryan Armstrong <ryan@cavaliercoder.com>
Steven Yu <steven@wordofeternity.org> -- Zabbix v2.4 support
=head1 SEE ALSO =head1 SEE ALSO
Guidelines for Authors and Reviewers of MIB Documents Guidelines for Authors and Reviewers of MIB Documents
https://www.ietf.org/rfc/rfc4181.txt https://www.ietf.org/rfc/rfc4181.txt
Next Generation Structure of Management Information (SMIng) Mappings to the Next Generation Structure of Management Information (SMIng) Mappings to the
Simple Network Management Protocol (SNMP) Simple Network Management Protocol (SNMP)
https://tools.ietf.org/html/rfc3781 https://tools.ietf.org/html/rfc3781
SNMP Table Basics SNMP Table Basics
http://www.webnms.com/snmp/help/snmpapi/snmpv3/table_handling/snmptables_basics.html http://www.webnms.com/snmp/help/snmpapi/snmpv3/table_handling/snmptables_basics.html
Zabbix Template Schema
v2.4 - https://www.zabbix.com/documentation/2.4/manual/xml_export_import/hosts
v3 - https://www.zabbix.com/documentation/3.0/manual/xml_export_import/hosts
=head1 SUBROUTINES =head1 SUBROUTINES
=cut =cut
use strict; use strict;
@ -192,7 +176,8 @@ my $opts = {
v3auth_protocol => 'md5', v3auth_protocol => 'md5',
v3auth_pass => '', v3auth_pass => '',
v3sec_protocol => 'des', v3sec_protocol => 'des',
v3sec_pass => '' v3sec_pass => '',
zabbix_ver => 3
}; };
# Capture calling args # Capture calling args
@ -222,6 +207,8 @@ GetOptions(
'x|privacy=s' => \$opts->{ v3sec_protocol }, # SNMPv3 Privacy protocol 'x|privacy=s' => \$opts->{ v3sec_protocol }, # SNMPv3 Privacy protocol
'X|privpass=s' => \$opts->{ v2sec_pass}, # SNMPv3 Privacy passphrase 'X|privpass=s' => \$opts->{ v2sec_pass}, # SNMPv3 Privacy passphrase
'z|zabbix_ver=i' => \$opts->{ zabbix_ver}, # Zabbix version
'check-delay=i' => \$opts->{ delay }, # Update interval in seconds 'check-delay=i' => \$opts->{ delay }, # Update interval in seconds
'disc-delay=i' => \$opts->{ disc_delay }, # Update interval in seconds 'disc-delay=i' => \$opts->{ disc_delay }, # Update interval in seconds
'history=i' => \$opts->{ history }, # History retention in days 'history=i' => \$opts->{ history }, # History retention in days
@ -272,8 +259,10 @@ my %item_base_template = (
username => '', username => '',
); );
# Item template for standard Template items my %item_template;
my %item_template = (
# Item template for standard Template items for Zabbix v3
my %item_template_v3 = (
data_type => '0', data_type => '0',
delay => $opts->{ delay }, # Update internal seconds delay => $opts->{ delay }, # Update internal seconds
delta => '0', # Change delta delta => '0', # Change delta
@ -286,7 +275,27 @@ my %item_template = (
valuemap => '', valuemap => '',
logtimefmt => '', logtimefmt => '',
); );
%item_template = (%item_base_template, %item_template);
# Item template for standard Template items for Zabbix v2
my %item_template_v2 = (
data_type => '0',
delay => $opts->{ delay }, # Update internal seconds
delta => '0', # Change delta
formula => '1', # Multiplier factor
history => $opts->{ history }, # History retention in days
inventory_link => '0',
multiplier => '0', # Enable multiplier
trends => $opts->{ trends }, # Trends retention in days
units => '',
valuemap => ''
);
if ( $opts->{zabbix_ver} == 3 ) {
%item_template = ( %item_base_template, %item_template_v3 );
}
else {
%item_template = ( %item_base_template, %item_template_v2 );
}
# Discovery rule template # Discovery rule template
my %disc_rule_template = ( my %disc_rule_template = (
@ -306,8 +315,8 @@ my %disc_rule_template = (
); );
%disc_rule_template = (%item_base_template, %disc_rule_template); %disc_rule_template = (%item_base_template, %disc_rule_template);
# SNMP Trap template # SNMP Trap template for Zabbix v3
my %trap_template = ( my %trap_template_v3 = (
allowed_hosts => '', allowed_hosts => '',
applications => [], applications => [],
authtype => 0, authtype => 0,
@ -345,6 +354,44 @@ my %trap_template = (
valuemap => '' valuemap => ''
); );
# SNMP Trap template for Zabbix v2
my %trap_template_v2 = (
allowed_hosts => '',
applications => [],
authtype => 0,
data_type => 0,
delay => '0',
delay_flex => '',
delta => 0,
description => '',
formula => 1,
history => $opts->{ history },
inventory_link => 0,
ipmi_sensor => '',
logtimefmt => 'hh:mm:ss dd/MM/yyyy',
multiplier => '0',
params => '',
password => '',
port => '',
privatekey => '',
publickey => '',
snmp_community => '',
snmp_oid => '',
snmpv3_authpassphrase => '',
snmpv3_authprotocol => 0,
snmpv3_contextname => '',
snmpv3_privpassphrase => '',
snmpv3_privprotocol => 0,
snmpv3_securitylevel => 0,
snmpv3_securityname => '',
status => ($opts->{ enableitems } ? ZBX_ITEM_ENABLED : ZBX_ITEM_DISABLED),
trends => $opts->{ trends },
type => ZBX_ITEM_TYPE_SNMPTRAP,
units => '',
username => '',
value_type => ZBX_VAL_TYPE_LOG
);
# Item prototype template # Item prototype template
my %item_proto_template = ( my %item_proto_template = (
application_prototypes => undef, application_prototypes => undef,
@ -359,7 +406,6 @@ my $valuemaps = {};
Parameters : (string) $malformed_utf8 Parameters : (string) $malformed_utf8
Returns : (string) $wellformed_utf8 Returns : (string) $wellformed_utf8
Description : Returns a sanitized UTF8 string, removing incompatable characters Description : Returns a sanitized UTF8 string, removing incompatable characters
=cut =cut
sub utf8_sanitize { sub utf8_sanitize {
my ($malformed_utf8) = @_; my ($malformed_utf8) = @_;
@ -369,12 +415,10 @@ sub utf8_sanitize {
} }
=head2 oid_path =head2 oid_path
Parameters : SNMP::MIB::Node $oid Parameters : SNMP::MIB::Node $oid
Returns : (String) $oid_path Returns : (String) $oid_path
Description : Returns the fully qualified textual path of a MIB node by Description : Returns the fully qualified textual path of a MIB node by
traversing the node's parents. traversing the node's parents.
=cut =cut
sub oid_path { sub oid_path {
my ($oid) = @_; my ($oid) = @_;
@ -389,12 +433,10 @@ sub oid_path {
} }
=head2 node_to_item =head2 node_to_item
Parameters : SNMP::MIB::Node $node Parameters : SNMP::MIB::Node $node
(Hash) $template (Hash) $template
Returns : (Hash) $item Returns : (Hash) $item
Description : Returns a Zabbix Item hash derived from the specified MIB OID Description : Returns a Zabbix Item hash derived from the specified MIB OID
=cut =cut
sub node_to_item { sub node_to_item {
my ($node, $template) = @_; my ($node, $template) = @_;
@ -490,7 +532,8 @@ sub node_to_item {
} }
# Process value maps # Process value maps
if (scalar keys % {$node->{ enums } }) { if ( $opts->{zabbix_ver} == 3 ) {
if (scalar keys % {$node->{ enums } }) {
my $map_name = "$node->{ moduleID }::$node->{ label }"; my $map_name = "$node->{ moduleID }::$node->{ label }";
# If the map_name is longer than 64 characters truncate to 64 characters # If the map_name is longer than 64 characters truncate to 64 characters
@ -510,23 +553,36 @@ sub node_to_item {
# Assign value map to item # Assign value map to item
$item->{ valuemap } = { name => $map_name }; $item->{ valuemap } = { name => $map_name };
}
else {
my $map_name = "$node->{ moduleID }::$node->{ label }";
# Assign value map to item
$item->{valuemap} = { name => $map_name };
}
} }
return $item; return $item;
} }
=head2 node_to_trapitem =head2 node_to_trapitem
Parameters : SNMP::MIB::Node $node Parameters : SNMP::MIB::Node $node
(Hash) $template (Hash) $template
Returns : (Hash) $item Returns : (Hash) $item
Description : Returns a Zabbix SNMP Trap Item hash derived from the Description : Returns a Zabbix SNMP Trap Item hash derived from the
specified MIB OID specified MIB OID
=cut =cut
sub node_to_trapitem { sub node_to_trapitem {
my ($node, $template) = @_; my ($node, $template) = @_;
$template = $template || \%trap_template;
if ( $opts->{zabbix_ver} == 3 ) {
$template = $template || \%trap_template_v3;
}
else {
$template = $template || \%trap_template_v2;
}
# Create item hash # Create item hash
my $item = { %{ $template } }; my $item = { %{ $template } };
@ -587,11 +643,9 @@ sub node_to_trapitem {
} }
=head2 node_is_current =head2 node_is_current
Parameters : SNMP::MIB::Node $node Parameters : SNMP::MIB::Node $node
Returns : (int) 0|1 Returns : (int) 0|1
Description : Returns true if the specified OID is not obsolete Description : Returns true if the specified OID is not obsolete
=cut =cut
sub node_is_current { sub node_is_current {
my ($node) = @_; my ($node) = @_;
@ -603,12 +657,10 @@ sub node_is_current {
} }
=head2 node_is_valid_scalar =head2 node_is_valid_scalar
Parameters : SNMP::MIB::Node $node Parameters : SNMP::MIB::Node $node
Returns : (int) 0|1 Returns : (int) 0|1
Description : Returns true if the specified OID is current, readable and Description : Returns true if the specified OID is current, readable and
defines a valid value type. defines a valid value type.
=cut =cut
sub node_is_valid_scalar { sub node_is_valid_scalar {
my ($node) = @_; my ($node) = @_;
@ -625,11 +677,9 @@ sub node_is_valid_scalar {
} }
=head2 node_is_valid_trap =head2 node_is_valid_trap
Parameters : SNMP::MIB::Node $node Parameters : SNMP::MIB::Node $node
Returns : (int) 0|1 Returns : (int) 0|1
Description : Returns true if the specified OID is an SNMP Trap Description : Returns true if the specified OID is an SNMP Trap
=cut =cut
sub node_is_valid_trap { sub node_is_valid_trap {
my ($node) = @_; my ($node) = @_;
@ -640,13 +690,11 @@ sub node_is_valid_trap {
} }
=head2 node_is_valid_table =head2 node_is_valid_table
Parameters : SNMP::MIB::Node $node Parameters : SNMP::MIB::Node $node
Returns : (int) 0|1 Returns : (int) 0|1
Description : Returns true if the specified OID is a valid table which is Description : Returns true if the specified OID is a valid table which is
current, readable and contains a single child (row current, readable and contains a single child (row
definition) definition)
=cut =cut
sub node_is_valid_table { sub node_is_valid_table {
my ($node) = @_; my ($node) = @_;
@ -672,14 +720,12 @@ sub node_is_valid_table {
} }
=head2 build_template =head2 build_template
Parameters : (hash) $template Parameters : (hash) $template
SNMP::MIB::NODE $node SNMP::MIB::NODE $node
Returns : (void) Returns : (void)
Description : Traverses a loaded MIB tree from the specified OID node Description : Traverses a loaded MIB tree from the specified OID node
a populates a Zabbix Template hash with items, discovery a populates a Zabbix Template hash with items, discovery
rules, item prototypes, groups and macros. rules, item prototypes, groups and macros.
=cut =cut
sub build_template { sub build_template {
my ($template, $node) = @_; my ($template, $node) = @_;
@ -764,17 +810,31 @@ sub build_template {
} }
} }
# Define macros in discovery key up to 255 chars if ( $opts->{zabbix_ver} == 3 ) {
# Define macros in discovery key up to 255 chars
# See: https://www.zabbix.com/documentation/3.0/manual/discovery/low_level_discovery#discovery_of_snmp_oids # See: https://www.zabbix.com/documentation/3.0/manual/discovery/low_level_discovery#discovery_of_snmp_oids
foreach my $column(@{ $row->{ children } }) { foreach my $column(@{ $row->{ children } }) {
if (node_is_valid_scalar($column)) { if (node_is_valid_scalar($column)) {
my $new_snmp_oid = $disc_rule->{ snmp_oid } . "{#" . uc($column->{ label }) . "}," . $column->{ objectID } . ","; my $new_snmp_oid = $disc_rule->{ snmp_oid } . "{#" . uc($column->{ label }) . "}," . $column->{ objectID } . ",";
if (length($new_snmp_oid) <= 255) { if (length($new_snmp_oid) <= 255) {
$disc_rule->{ snmp_oid } = $new_snmp_oid; $disc_rule->{ snmp_oid } = $new_snmp_oid;
}
}
}
$disc_rule->{ snmp_oid } = substr($disc_rule->{ snmp_oid }, 0, -1) . "]";
}
else {
# find entry index colum
foreach my $column ( @{ $row->{children} } ) {
if ( node_is_valid_scalar($column) ) {
if ( $column->{label} =~ m/Index$/ ) {
#print STDERR
#"Warning: $row->{ moduleID }:: $row->{ label }:: $column->{label} $column->{ objectID }, Index Found\n";
$disc_rule->{snmp_oid} = $column->{objectID};
}
} }
} }
} }
$disc_rule->{ snmp_oid } = substr($disc_rule->{ snmp_oid }, 0, -1) . "]";
# Fetch an arbitrary column OID for Zabbix to use for discovery # Fetch an arbitrary column OID for Zabbix to use for discovery
my $index_oid = $row->{ children }[0]; my $index_oid = $row->{ children }[0];
@ -800,7 +860,15 @@ sub build_template {
$proto->{ applications } = [{ name => $appname }]; $proto->{ applications } = [{ name => $appname }];
$template->{ apptags }->{ $appname } = 1; $template->{ apptags }->{ $appname } = 1;
push(@{ $disc_rule->{ item_prototypes } }, $proto); if ( $opts->{zabbix_ver} == 3 ) {
push(@{ $disc_rule->{ item_prototypes } }, $proto);
}
else {
# No need for Indexer to be added in Zabbix 2.4
if ( $proto->{name} !~ m/Index/ ) {
push(@{ $disc_rule->{ item_prototypes } }, $proto);
}
}
} }
} }
} }
@ -870,9 +938,12 @@ if (!$oid_root || $oid_root->{ objectID } ne $opts->{ oid }) {
@{ $template->{ applications } } = map { { name => $_ } } keys %{ $template->{ apptags } }; @{ $template->{ applications } } = map { { name => $_ } } keys %{ $template->{ apptags } };
delete($template->{ apptags }); delete($template->{ apptags });
# Build XML document # Build XML document
my $time = time(); my $time = time();
my $output = {
# version 3
my $output_v3 = {
version => '3.0', version => '3.0',
date => time2str("%Y-%m-%dT%H:%M:%SZ", $time), date => time2str("%Y-%m-%dT%H:%M:%SZ", $time),
groups => $template->{ groups }, groups => $template->{ groups },
@ -882,6 +953,16 @@ if (!$oid_root || $oid_root->{ objectID } ne $opts->{ oid }) {
value_maps => [$valuemaps] value_maps => [$valuemaps]
}; };
# version 2
my $output_v2 = {
version => '2.0',
date => time2str( "%Y-%m-%dT%H:%M:%SZ", $time ),
groups => $template->{groups},
templates => [$template],
triggers => [],
graphs => []
};
# Output stream # Output stream
my $fh = *STDOUT; my $fh = *STDOUT;
if ($opts->{ filename }) { if ($opts->{ filename }) {
@ -889,7 +970,9 @@ if (!$oid_root || $oid_root->{ objectID } ne $opts->{ oid }) {
} }
# Output XML # Output XML
XMLout($output,
if ( $opts->{zabbix_ver} == 3 ) {
XMLout($output_v3,
OutputFile => \$fh, OutputFile => \$fh,
XMLDecl => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", XMLDecl => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
RootName => 'zabbix_export', RootName => 'zabbix_export',
@ -908,8 +991,30 @@ if (!$oid_root || $oid_root->{ objectID } ne $opts->{ oid }) {
'host_prototypes' => 'host_prototype', 'host_prototypes' => 'host_prototype',
'value_maps' => %{ $valuemaps } ? 'value_map' : undef, 'value_maps' => %{ $valuemaps } ? 'value_map' : undef,
'mappings' => 'mapping' 'mappings' => 'mapping'
} }
); );
}
else {
XMLout($output_v2,
OutputFile => \$fh,
XMLDecl => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
RootName => 'zabbix_export',
NoAttr => 1,
SuppressEmpty => undef,
GroupTags => {
'applications' => 'application',
'groups' => 'group',
'templates' => 'template',
'items' => 'item',
'macros' => 'macro',
'discovery_rules' => 'discovery_rule',
'item_prototypes' => 'item_prototype',
'trigger_prototypes' => 'trigger_prototype',
'graph_prototypes' => 'graph_prototype',
'host_prototypes' => 'host_prototype'
}
);
}
if ($opts->{ filename }) { if ($opts->{ filename }) {
close $fh; close $fh;