From 2f8de1afe933971661abe072e09c82aa736984d6 Mon Sep 17 00:00:00 2001 From: Steven Yu Date: Wed, 24 Aug 2016 15:27:44 +1000 Subject: [PATCH] Update mib2zabbix.pl Format code to align with the original --- mib2zabbix.pl | 1278 ++++++++++++++++++++++--------------------------- 1 file changed, 564 insertions(+), 714 deletions(-) diff --git a/mib2zabbix.pl b/mib2zabbix.pl index 4c7a256..2378082 100755 --- a/mib2zabbix.pl +++ b/mib2zabbix.pl @@ -1,17 +1,11 @@ #!/usr/bin/perl - =pod - =head1 NAME - mib2zabbix.pl - SNMP MIB to Zabbix Template - =head1 SYNOPSIS - mib2zabbix.pl -o [OPTIONS]... Export loaded SNMP MIB OIDs to Zabbix Template XML - -f, --filename=PATH output filename (default: stdout) -N, --name=STRING template name (default: OID label) @@ -24,11 +18,9 @@ Export loaded SNMP MIB OIDs to Zabbix Template XML -p, --port=PORT SNMP UDP port number (default: 161) SNMP Version 1 or 2c specific - -c, --community=STRING SNMP community string (default: 'public') SNMP Version 3 specific - -L, --level=LEVEL security level (noAuthNoPriv|authNoPriv|authPriv) -n, --context=CONTEXT context name -u, --username=USERNAME security name @@ -38,11 +30,9 @@ SNMP Version 3 specific -X, --privpass=PASSPHRASE privacy passphrase 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) --disc-delay=SECONDS discovery interval in seconds (default: 3600) --history=DAYS history retention in days (default: 7) @@ -51,43 +41,28 @@ Zabbix item configuration Help -h, --help print this message - =head1 DESCRIPTION - B will export a loaded MIB tree into a Zabbix Template starting from the OID root specified. - Requires: Zabbix v2.4 or 3, Perl v5, Pod::Usage, XML::Simple, Net-SNMP - =head1 AUTHOR - Ryan Armstrong - Steven Yu -- Zabbix v2.4 support - =head1 SEE ALSO - Guidelines for Authors and Reviewers of MIB Documents https://www.ietf.org/rfc/rfc4181.txt - Next Generation Structure of Management Information (SMIng) Mappings to the Simple Network Management Protocol (SNMP) https://tools.ietf.org/html/rfc3781 - SNMP Table Basics 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 - =cut use strict; - #use warnings; use Cwd 'abs_path'; @@ -101,17 +76,17 @@ use SNMP; use XML::Simple; # Get path info as constants -use constant SCRIPT_NAME => basename($0); -use constant BASE_PATH => dirname( abs_path($0) ); +use constant SCRIPT_NAME => basename($0); +use constant BASE_PATH => dirname(abs_path($0)); -use constant ZBX_SERVER_CONF => '/etc/zabbix/zabbix_server.conf'; -use constant ZBX_WEB_CONF => '/etc/zabbix/web/zabbix.conf.php'; +use constant ZBX_SERVER_CONF => '/etc/zabbix/zabbix_server.conf'; +use constant ZBX_WEB_CONF => '/etc/zabbix/web/zabbix.conf.php'; # For Zabbix type constants see: # https://www.zabbix.com/documentation/3.0/manual/api/reference/item/object # Zabbix Item status -use constant ZBX_ITEM_ENABLED => 0; -use constant ZBX_ITEM_DISABLED => 1; +use constant ZBX_ITEM_ENABLED => 0; +use constant ZBX_ITEM_DISABLED => 1; # Zabbix Item Type IDs use constant ZBX_ITEM_TYPE_SNMPV1 => 1; @@ -120,230 +95,204 @@ use constant ZBX_ITEM_TYPE_SNMPV3 => 6; use constant ZBX_ITEM_TYPE_SNMPTRAP => 17; # Zabbix Item Value Type IDs -use constant ZBX_VAL_TYPE_FLOAT => 0; -use constant ZBX_VAL_TYPE_CHAR => 1; -use constant ZBX_VAL_TYPE_LOG => 2; -use constant ZBX_VAL_TYPE_UINT => 3; -use constant ZBX_VAL_TYPE_TEXT => 4; +use constant ZBX_VAL_TYPE_FLOAT => 0; +use constant ZBX_VAL_TYPE_CHAR => 1; +use constant ZBX_VAL_TYPE_LOG => 2; +use constant ZBX_VAL_TYPE_UINT => 3; +use constant ZBX_VAL_TYPE_TEXT => 4; # Zabbix Item Storage types (delta) -use constant ZBX_ITEM_STORE_ASIS => 0; # Store value as is -use constant ZBX_ITEM_STORE_SPEED => 1; # Delta, speed per second -use constant ZBX_ITEM_STORE_CHANGE => 2; # Delta, simple change +use constant ZBX_ITEM_STORE_ASIS => 0; # Store value as is +use constant ZBX_ITEM_STORE_SPEED => 1; # Delta, speed per second +use constant ZBX_ITEM_STORE_CHANGE => 2; # Delta, simple change # Zabbix Item SNMPv3 constants -use constant ZBX_V3_PRIV_DES => 0; -use constant ZBX_V3_PRIV_AES => 1; -use constant ZBX_V3_AUTH_MD5 => 0; -use constant ZBX_V3_AUTH_SHA => 1; -use constant ZBX_V3_SEC_NOAUTHNOPRIV => 0; -use constant ZBX_V3_SEC_AUTHNOPRIV => 1; -use constant ZBX_V3_SEC_AUTHPRIV => 2; +use constant ZBX_V3_PRIV_DES => 0; +use constant ZBX_V3_PRIV_AES => 1; +use constant ZBX_V3_AUTH_MD5 => 0; +use constant ZBX_V3_AUTH_SHA => 1; +use constant ZBX_V3_SEC_NOAUTHNOPRIV => 0; +use constant ZBX_V3_SEC_AUTHNOPRIV => 1; +use constant ZBX_V3_SEC_AUTHPRIV => 2; # SNMP Type -> Zabbix type mapping my $type_map = { - 'BITS' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type - 'COUNTER' => ZBX_VAL_TYPE_UINT - , # Zabbix 'Numeric Unsigned' value type for an unsigned integer - 'COUNTER32' => ZBX_VAL_TYPE_UINT - , # Zabbix 'Numeric Unsigned' value type for an unsigned integer - 'COUNTER64' => ZBX_VAL_TYPE_UINT - , # Zabbix 'Numeric Unsigned' value type for an unsigned integer - 'GAUGE' => ZBX_VAL_TYPE_UINT - , # Zabbix 'Numeric Unsigned' value type for an unsigned integer - 'GAUGE32' => ZBX_VAL_TYPE_UINT - , # Zabbix 'Numeric Unsigned' value type for an unsigned integer - 'INTEGER' => ZBX_VAL_TYPE_FLOAT - , # Zabbix 'Numeric Float' value type for an signed integer - 'INTEGER32' => ZBX_VAL_TYPE_FLOAT - , # Zabbix 'Numeric Float' value type for an signed 32 bit integer - 'IPADDR' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type for an IP address - 'NETADDDR' => - ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type for a network address - 'NOTIF' => ZBX_ITEM_TYPE_SNMPTRAP, # Zabbix 'SNMP Trap' item type - 'TRAP' => ZBX_ITEM_TYPE_SNMPTRAP, # Zabbix 'SNMP Trap' item type - 'OBJECTID' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type for an OID - 'OCTETSTR' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type - 'OPAQUE' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type - 'TICKS' => - ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' for a Module 232 timestamp - 'UNSIGNED32' => - ZBX_VAL_TYPE_UINT # Zabbix 'Numeric Unsigned' value type for an unsigned 32bit integer + 'BITS' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type + 'COUNTER' => ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' value type for an unsigned integer + 'COUNTER32' => ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' value type for an unsigned integer + 'COUNTER64' => ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' value type for an unsigned integer + 'GAUGE' => ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' value type for an unsigned integer + 'GAUGE32' => ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' value type for an unsigned integer + 'INTEGER' => ZBX_VAL_TYPE_FLOAT, # Zabbix 'Numeric Float' value type for an signed integer + 'INTEGER32' => ZBX_VAL_TYPE_FLOAT, # Zabbix 'Numeric Float' value type for an signed 32 bit integer + 'IPADDR' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type for an IP address + 'NETADDDR' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type for a network address + 'NOTIF' => ZBX_ITEM_TYPE_SNMPTRAP, # Zabbix 'SNMP Trap' item type + 'TRAP' => ZBX_ITEM_TYPE_SNMPTRAP, # Zabbix 'SNMP Trap' item type + 'OBJECTID' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type for an OID + 'OCTETSTR' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type + 'OPAQUE' => ZBX_VAL_TYPE_TEXT, # Zabbix 'Text' value type + 'TICKS' => ZBX_VAL_TYPE_UINT, # Zabbix 'Numeric Unsigned' for a Module 232 timestamp + 'UNSIGNED32' => ZBX_VAL_TYPE_UINT # Zabbix 'Numeric Unsigned' value type for an unsigned 32bit integer }; # SNMP Version -> Zabbix item type mapping my $snmpver_map = { - 1 => ZBX_ITEM_TYPE_SNMPV1, # Zabbix SNMPv1 Agent type for SNMPv1 - 2 => ZBX_ITEM_TYPE_SNMPV2, # Zabbix SNMPv2 Agent type for SNMPv2 - 3 => ZBX_ITEM_TYPE_SNMPV3 # Zabbix SNMPv3 Agent type for SNMPv3 + 1 => ZBX_ITEM_TYPE_SNMPV1, # Zabbix SNMPv1 Agent type for SNMPv1 + 2 => ZBX_ITEM_TYPE_SNMPV2, # Zabbix SNMPv2 Agent type for SNMPv2 + 3 => ZBX_ITEM_TYPE_SNMPV3 # Zabbix SNMPv3 Agent type for SNMPv3 }; # SNMP Auth config -> Zabbix item auth config my $snmpv3_auth_level_map = { - 'noAuthNoPriv' => ZBX_V3_SEC_NOAUTHNOPRIV, - 'authNoPriv' => ZBX_V3_SEC_AUTHNOPRIV, - 'authPriv' => ZBX_V3_SEC_AUTHPRIV + 'noAuthNoPriv' => ZBX_V3_SEC_NOAUTHNOPRIV, + 'authNoPriv' => ZBX_V3_SEC_AUTHNOPRIV, + 'authPriv' => ZBX_V3_SEC_AUTHPRIV }; my $snmpv3_auth_protocol_map = { - 'md5' => ZBX_V3_AUTH_MD5, - 'sha' => ZBX_V3_AUTH_SHA + 'md5' => ZBX_V3_AUTH_MD5, + 'sha' => ZBX_V3_AUTH_SHA }; my $snmpv3_sec_protocol_map = { - 'des' => ZBX_V3_PRIV_DES, - 'aes' => ZBX_V3_PRIV_AES + 'des' => ZBX_V3_PRIV_DES, + 'aes' => ZBX_V3_PRIV_AES }; # Default command line options -my $opts = { - delay => 60, # 1 minute check interval - disc_delay => 3600, # Hourly discovery - enableitems => 0, # Disable items - group => 'Templates', - history => 7, - trends => 365, - list => 0, - maxdepth => -1, - oid => '.1', - use_macros => 0, - snmpcomm => 'public', - snmpport => 161, - snmpver => 2, - v3auth_level => 'noAuthNoPriv', - v3context => '', - v3user => '', - v3auth_protocol => 'md5', - v3auth_pass => '', - v3sec_protocol => 'des', - v3sec_pass => '', - zabbix_ver => 3 +my $opts = { + delay => 60, # 1 minute check interval + disc_delay => 3600, # Hourly discovery + enableitems => 0, # Disable items + group => 'Templates', + history => 7, + trends => 365, + list => 0, + maxdepth => -1, + oid => '.1', + use_macros => 0, + snmpcomm => 'public', + snmpport => 161, + snmpver => 2, + v3auth_level => 'noAuthNoPriv', + v3context => '', + v3user => '', + v3auth_protocol => 'md5', + v3auth_pass => '', + v3sec_protocol => 'des', + v3sec_pass => '', + zabbix_ver => 3 }; # Capture calling args my $cmd = basename($0) . " @ARGV"; # Get command line options -Getopt::Long::Configure( "posix_default", "bundling" ); +Getopt::Long::Configure ("posix_default", "bundling"); GetOptions( - 'f|filename=s' => \$opts->{filename}, # Filename to output + 'f|filename=s' => \$opts->{ filename }, # Filename to output + + 'N|name=s' => \$opts->{ name }, # Template name + 'G|group=s' => \$opts->{ group }, # Template group + 'o|oid=s' => \$opts->{ oid }, # Root OID to export - 'N|name=s' => \$opts->{name}, # Template name - 'G|group=s' => \$opts->{group}, # Template group - 'o|oid=s' => \$opts->{oid}, # Root OID to export + 'e|enable-items' => \$opts->{ enableitems }, # Enable template items + + 'v|snmpver=i' => \$opts->{ snmpver }, # SNMP Version + 'p|port=i' => \$opts->{ snmpport }, # SNMP Port + + 'c|community=s' => \$opts->{ snmpcomm }, # SNMP Community string + + 'L|level=s' => \$opts->{ v3auth_level }, # SNMPv3 Authentication level + 'n|context=s' => \$opts->{ v3context }, # SNMPv3 Security Context + 'u|username=s' => \$opts->{ v3user }, # SNMPv3 Authentication username + 'a|auth=s' => \$opts->{ v3auth_protocol }, # SNMPv3 Authentication protocol + 'A|authpass=s' => \$opts->{ v3auth_pass }, # SNMPv3 Authentication passphrase + 'x|privacy=s' => \$opts->{ v3sec_protocol }, # SNMPv3 Privacy protocol + 'X|privpass=s' => \$opts->{ v2sec_pass}, # SNMPv3 Privacy passphrase - 'e|enable-items' => \$opts->{enableitems}, # Enable template items + 'z|zabbix_ver=i' => \$opts->{zabbix_ver}, # Zabbix version - 'v|snmpver=i' => \$opts->{snmpver}, # SNMP Version - 'p|port=i' => \$opts->{snmpport}, # SNMP Port - 'c|community=s' => \$opts->{snmpcomm}, # SNMP Community string - - 'L|level=s' => \$opts->{v3auth_level}, # SNMPv3 Authentication level - 'n|context=s' => \$opts->{v3context}, # SNMPv3 Security Context - 'u|username=s' => \$opts->{v3user}, # SNMPv3 Authentication username - 'a|auth=s' => \$opts->{v3auth_protocol}, # SNMPv3 Authentication protocol - 'A|authpass=s' => \$opts->{v3auth_pass}, # SNMPv3 Authentication passphrase - 'x|privacy=s' => \$opts->{v3sec_protocol}, # SNMPv3 Privacy protocol - '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 - 'disc-delay=i' => \$opts->{disc_delay}, # Update interval in seconds - 'history=i' => \$opts->{history}, # History retention in days - 'trends=i' => \$opts->{trends}, # Trends retention in days - - 'h|help' => \$opts->{help} + 'check-delay=i' => \$opts->{ delay }, # Update interval in seconds + 'disc-delay=i' => \$opts->{ disc_delay }, # Update interval in seconds + 'history=i' => \$opts->{ history }, # History retention in days + 'trends=i' => \$opts->{ trends }, # Trends retention in days + + 'h|help' => \$opts->{ help } ) || pod2usage(); # Print usage if requested -pod2usage( { -exitval => 0 } ) if ( $opts->{help} ); +pod2usage({ -exitval => 0 }) if ($opts->{ help }); # Validate SNMPv3 settings -if ( $opts->{snmpver} == 3 ) { - $opts->{snmpcomm} = ''; - - die("Unknown authentication level '$opts->{ v3auth_level }'") - unless defined( $snmpv3_auth_level_map->{ $opts->{v3auth_level} } ); - $opts->{v3auth_level} = $snmpv3_auth_level_map->{ $opts->{v3auth_level} }; - - die("Unknown authentical protocol '$opts->{ v3auth_protocol }'") - unless defined( $snmpv3_auth_protocol_map->{ $opts->{v3auth_protocol} } ); - $opts->{v3auth_protocol} = - $snmpv3_auth_protocol_map->{ $opts->{v3auth_protocol} }; - - die("Unknown privacy protocol '$opts->{ v3sec_protocol }'") - unless defined( $snmpv3_sec_protocol_map->{ $opts->{v3sec_protocol} } ); - $opts->{v3sec_protocol} = - $snmpv3_sec_protocol_map->{ $opts->{v3sec_protocol} }; +if ($opts->{ snmpver } == 3) { + $opts->{ snmpcomm } = ''; + + die("Unknown authentication level '$opts->{ v3auth_level }'") unless defined($snmpv3_auth_level_map->{ $opts->{ v3auth_level } }); + $opts->{ v3auth_level } = $snmpv3_auth_level_map->{ $opts->{ v3auth_level } }; + + die("Unknown authentical protocol '$opts->{ v3auth_protocol }'") unless defined($snmpv3_auth_protocol_map->{ $opts->{ v3auth_protocol } }); + $opts->{ v3auth_protocol } = $snmpv3_auth_protocol_map->{ $opts->{ v3auth_protocol } }; + + die("Unknown privacy protocol '$opts->{ v3sec_protocol }'") unless defined ($snmpv3_sec_protocol_map->{ $opts->{ v3sec_protocol } }); + $opts->{ v3sec_protocol } = $snmpv3_sec_protocol_map->{ $opts->{ v3sec_protocol } }; } # Base template for Template Items, Discovery Rules and Item Prototypes # See: https://www.zabbix.com/documentation/2.2/manual/api/reference/item/object my %item_base_template = ( - allowed_hosts => '', - applications => [], - authtype => '0', - delay_flex => '', - ipmi_sensor => '', - params => '', - password => '', - port => '{$SNMP_PORT}', # Use macro for SNMP UDP Port - privatekey => '', - publickey => '', - snmp_community => $opts->{snmpver} < 3 - ? '{$SNMP_COMMUNITY}' - : '', # Use macro for SNMP Community string - snmpv3_authpassphrase => $opts->{snmpver} == 3 - ? '{$SNMP_AUTHPASS}' - : '', # Use macro for SNMPv3 Authentication passphrase - snmpv3_authprotocol => $opts->{snmpver} == 3 ? $opts->{v3auth_protocol} - : '0', - snmpv3_contextname => $opts->{snmpver} == 3 ? '{$SNMP_CONTEXT}' - : '', # Use macro for SNMPv3 context name - snmpv3_privpassphrase => $opts->{snmpver} == 3 - ? '{$SNMP_PRIVPASS}' - : '', # Use macro for SNMPv3 Privacy passphrase - snmpv3_privprotocol => $opts->{snmpver} == 3 ? $opts->{v3sec_protocol} - : '0', - snmpv3_securitylevel => $opts->{snmpver} == 3 ? $opts->{v3auth_level} : '0', - snmpv3_securityname => $opts->{snmpver} == 3 ? '{$SNMP_USER}' - : '', # Use macro for SNMPv3 Username - status => ( $opts->{enableitems} ? ZBX_ITEM_ENABLED : ZBX_ITEM_DISABLED ) - , # Enabled (0) | Disabled (1) - username => '', + allowed_hosts => '', + applications => [], + authtype => '0', + delay_flex => '', + ipmi_sensor => '', + params => '', + password => '', + port => '{$SNMP_PORT}', # Use macro for SNMP UDP Port + privatekey => '', + publickey => '', + snmp_community => $opts->{ snmpver } < 3 ? '{$SNMP_COMMUNITY}' : '', # Use macro for SNMP Community string + snmpv3_authpassphrase => $opts->{ snmpver } == 3 ? '{$SNMP_AUTHPASS}' : '', # Use macro for SNMPv3 Authentication passphrase + snmpv3_authprotocol => $opts->{ snmpver } == 3 ? $opts->{ v3auth_protocol } : '0', + snmpv3_contextname => $opts->{ snmpver } == 3 ? '{$SNMP_CONTEXT}' : '', # Use macro for SNMPv3 context name + snmpv3_privpassphrase => $opts->{ snmpver } == 3 ? '{$SNMP_PRIVPASS}' : '', # Use macro for SNMPv3 Privacy passphrase + snmpv3_privprotocol => $opts->{ snmpver } == 3 ? $opts->{ v3sec_protocol } : '0', + snmpv3_securitylevel => $opts->{ snmpver } == 3 ? $opts->{ v3auth_level } : '0', + snmpv3_securityname => $opts->{ snmpver } == 3 ? '{$SNMP_USER}' : '', # Use macro for SNMPv3 Username + status => ($opts->{ enableitems } ? ZBX_ITEM_ENABLED : ZBX_ITEM_DISABLED), # Enabled (0) | Disabled (1) + username => '', ); my %item_template; # Item template for standard Template items for Zabbix v3 my %item_template_v3 = ( - 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 => '', - logtimefmt => '', + 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 => '', + logtimefmt => '', ); # 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 - valuemap => '', - units => '', + 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 => '', ); if ( $opts->{zabbix_ver} == 3 ) { @@ -355,287 +304,259 @@ else { # Discovery rule template my %disc_rule_template = ( - delay => $opts->{disc_delay}, - lifetime => '30', - filter => { - evaltype => 0, - formula => undef, - conditions => undef + delay => $opts->{ disc_delay }, + lifetime => '30', + filter => { + evaltype => 0, + formula => undef, + conditions => undef }, # The following items must be created as unique refs for each item - host_prototypes => [], - item_prototypes => [], - graph_prototypes => [], - trigger_prototypes => [] + host_prototypes => [], + item_prototypes => [], + graph_prototypes => [], + trigger_prototypes => [] ); -%disc_rule_template = ( %item_base_template, %disc_rule_template ); +%disc_rule_template = (%item_base_template, %disc_rule_template); # SNMP Trap template for Zabbix v3 my %trap_template_v3 = ( - 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, - valuemap => '' + 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, + 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 + 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 -my %item_proto_template = ( application_prototypes => undef, ); - -%item_proto_template = ( %item_template, %item_proto_template ); +my %item_proto_template = ( + application_prototypes => undef, +); +%item_proto_template = (%item_template, %item_proto_template); # Global value maps array my $valuemaps = {}; =head2 utf8_santize - Parameters : (string) $malformed_utf8 Returns : (string) $wellformed_utf8 Description : Returns a sanitized UTF8 string, removing incompatable characters - =cut - sub utf8_sanitize { my ($malformed_utf8) = @_; - - my $octets = decode( 'UTF-8', $malformed_utf8, Encode::FB_DEFAULT ); - return encode( 'UTF-8', $octets, Encode::FB_CROAK ); + + my $octets = decode('UTF-8', $malformed_utf8, Encode::FB_DEFAULT); + return encode('UTF-8', $octets, Encode::FB_CROAK); } =head2 oid_path - Parameters : SNMP::MIB::Node $oid Returns : (String) $oid_path Description : Returns the fully qualified textual path of a MIB node by traversing the node's parents. - =cut - sub oid_path { my ($oid) = @_; - - my $path = $oid->{label}; + + my $path = $oid->{ label }; my $node = $oid; - while ( $node = $node->{parent} ) { + while ($node = $node->{ parent }) { $path = "$node->{ label }.$path"; } - + return $path; } =head2 node_to_item - Parameters : SNMP::MIB::Node $node (Hash) $template Returns : (Hash) $item Description : Returns a Zabbix Item hash derived from the specified MIB OID - =cut - sub node_to_item { - my ( $node, $template ) = @_; + my ($node, $template) = @_; $template = $template || \%item_template; - + # Create item hash - my $item = { %{$template} }; - - $item->{name} = $node->{label}; - $item->{snmp_oid} = $node->{objectID}; - if ( $node->{units} ) { - -# Convert unit to Zabbix postfix -# See 'Units' section of https://www.zabbix.com/documentation/3.0/manual/config/items/item - if ( $node->{units} =~ /^seconds$/ ) { - $item->{units} = 's'; - } - elsif ( $node->{units} =~ /^(hundreds of seconds)$/i ) { - $item->{units} = 's'; - $item->{multiplier} = '1'; - $item->{formula} = '100'; - } - elsif ( $node->{units} =~ /^(milliseconds|milli-seconds)$/i ) { - $item->{units} = 's'; - $item->{multiplier} = '1'; - $item->{formula} = '.001'; - } - elsif ( $node->{units} =~ /^microseconds$/i ) { - $item->{units} = 's'; - $item->{multiplier} = '1'; - $item->{formula} = '.000001'; - } - elsif ( $node->{units} =~ /^(octets|bytes)$/i ) { - $item->{units} = 'B'; - } - elsif ( $node->{units} =~ /^(k-octets|kbytes|kb)$/i ) { - $item->{units} = 'B'; - $item->{multiplier} = '1'; - $item->{formula} = '.001'; - } - elsif ( $node->{units} =~ /^(bits per second)$/i ) { - $item->{units} = 'b'; - } - elsif ( $node->{units} =~ /^(kbps|kilobits per second)$/i ) { - $item->{units} = 'b'; - $item->{multiplier} = '1'; - $item->{formula} = '.001'; - } - elsif ( $node->{units} =~ /^percent$/i ) { - $item->{units} = '%'; - } - elsif ( $node->{units} =~ /\/s$/i ) { - + my $item = { %{ $template } }; + + $item->{ name } = $node->{ label }; + $item->{ snmp_oid } = $node->{ objectID }; + if ($node->{ units }) { + # Convert unit to Zabbix postfix + # See 'Units' section of https://www.zabbix.com/documentation/3.0/manual/config/items/item + if ($node->{ units } =~ /^seconds$/) { + $item->{ units } = 's'; + } elsif ($node->{ units } =~ /^(hundreds of seconds)$/i) { + $item->{ units } = 's'; + $item->{ multiplier } = '1'; + $item->{ formula } = '100'; + } elsif ($node->{ units } =~ /^(milliseconds|milli-seconds)$/i) { + $item->{ units } = 's'; + $item->{ multiplier } = '1'; + $item->{ formula } = '.001'; + } elsif ($node->{ units } =~ /^microseconds$/i) { + $item->{ units } = 's'; + $item->{ multiplier } = '1'; + $item->{ formula } = '.000001'; + } elsif ($node->{ units } =~ /^(octets|bytes)$/i) { + $item->{ units } = 'B'; + } elsif ($node->{ units } =~ /^(k-octets|kbytes|kb)$/i) { + $item->{ units } = 'B'; + $item->{ multiplier } = '1'; + $item->{ formula } = '.001'; + } elsif ($node->{ units } =~ /^(bits per second)$/i) { + $item->{ units } = 'b'; + } elsif ($node->{ units } =~ /^(kbps|kilobits per second)$/i) { + $item->{ units } = 'b'; + $item->{ multiplier } = '1'; + $item->{ formula } = '.001'; + } elsif ($node->{ units } =~ /^percent$/i) { + $item->{ units } = '%'; + } elsif ($node->{ units } =~ /\/s$/i) { # truncate /s (/sec will be added later) - $item->{units} = substr( $node->{units}, 0, -2 ) . "/sec"; - } - else { - + $item->{ units } = substr($node->{ units }, 0, -2) . "/sec"; + } else { # default to original - $item->{units} = $node->{units}; + $item->{ units } = $node->{ units }; } } - + # Merge in item defaults - %{$item} = ( %{$template}, %{$item} ); - + %{ $item } = (%{ $template }, %{ $item } ); + # Create SNMP Agent item - $item->{type} = $snmpver_map->{ $opts->{snmpver} }; - + $item->{ type } = $snmpver_map->{ $opts->{ snmpver } }; + # Item key - $item->{key} = "$node->{ moduleID }.$node->{ label }"; - + $item->{ key } = "$node->{ moduleID }.$node->{ label }"; + # Map value type (Ignore for OID Table Entry Rows) - if ( $node->{type} ) { - $item->{value_type} = $type_map->{ $node->{type} }; - if ( !defined( $item->{value_type} ) ) { - print STDERR -"No type mapping found for type $node->{ type } in $node->{ objectID }\n"; + if ($node->{ type }) { + $item->{ value_type } = $type_map->{ $node->{ type } }; + if (!defined($item->{ value_type })) { + print STDERR "No type mapping found for type $node->{ type } in $node->{ objectID }\n"; } } - + # Set storage type to Delta for MIB counter types - if ( $node->{type} ~~ [ 'COUNTER', 'COUNTER32', 'COUNTER64' ] ) { - $item->{delta} = ZBX_ITEM_STORE_SPEED; + if ( $node->{ type } ~~ ['COUNTER', 'COUNTER32', 'COUNTER64']) { + $item->{ delta } = ZBX_ITEM_STORE_SPEED; - if ( $item->{units} =~ /^s$/ ) { - $item->{units} = '/sec'; - } - elsif ( $item->{units} =~ /^b$/i ) { - $item->{units} .= 'ps'; - } - else { - $item->{units} .= '/sec'; + if ($item->{ units } =~ /^s$/) { + $item->{ units } = '/sec'; + } elsif ($item->{ units } =~ /^b$/i) { + $item->{ units } .= 'ps'; + } else { + $item->{ units } .= '/sec'; } } - + # Translate SNMP Ticks - if ( $node->{type} eq 'TICKS' ) { - $item->{multiplier} = '1'; - $item->{formula} = '.01'; - $item->{units} = 'uptime'; + if ($node->{ type } eq 'TICKS') { + $item->{ multiplier } = '1'; + $item->{ formula } = '.01'; + $item->{ units } = 'uptime'; } - + # Parse item desciption - $item->{description} = utf8_sanitize( $node->{description} ); - if ( $item->{description} ) { - $item->{description} =~ - s/^\s+|\s+$|\n//g; # Trim left/right whitespace and newlines - $item->{description} =~ s/\s{2,}/ /g; # Remove padding + $item->{ description } = utf8_sanitize($node->{ description }); + if ($item->{ description }) { + $item->{ description } =~ s/^\s+|\s+$|\n//g; # Trim left/right whitespace and newlines + $item->{ description } =~ s/\s{2,}/ /g; # Remove padding } - + # Process value maps if ( $opts->{zabbix_ver} == 3 ) { - if ( scalar keys %{ $node->{enums} } ) { - my $map_name = "$node->{ moduleID }::$node->{ label }"; + if (scalar keys % {$node->{ enums } }) { + my $map_name = "$node->{ moduleID }::$node->{ label }"; # If the map_name is longer than 64 characters truncate to 64 characters # to match maximum database field length. - if ( length($map_name) > 64 ) { - $map_name = substr( $map_name, 0, 61 ) . "..."; - } + if (length($map_name) > 64) { + $map_name = substr($map_name,0,61) . "..."; + } - # add template value map for Zabbix version 3 - $valuemaps->{$map_name}->{'mappings'} = []; - foreach ( keys %{ $node->{enums} } ) { - push( - @{ $valuemaps->{$map_name}->{'mappings'} }, - { - 'value' => $node->{enums}->{$_}, - 'newvalue' => $_ - } - ); - } + # add template value map + $valuemaps->{ $map_name }->{ 'mappings' } = []; + foreach(keys %{ $node->{ enums } }) { + push(@{ $valuemaps->{ $map_name }->{ 'mappings' } }, { + 'value' => $node->{ enums }->{ $_ }, + 'newvalue' => $_ + }); + } - # Assign value map to item - $item->{valuemap} = { name => $map_name }; + # Assign value map to item + $item->{ valuemap } = { name => $map_name }; } else { my $map_name = "$node->{ moduleID }::$node->{ label }"; @@ -643,25 +564,21 @@ sub node_to_item { # Assign value map to item $item->{valuemap} = { name => $map_name }; } - } return $item; } =head2 node_to_trapitem - Parameters : SNMP::MIB::Node $node (Hash) $template Returns : (Hash) $item Description : Returns a Zabbix SNMP Trap Item hash derived from the specified MIB OID - =cut - sub node_to_trapitem { - my ( $node, $template ) = @_; - + my ($node, $template) = @_; + if ( $opts->{zabbix_ver} == 3 ) { $template = $template || \%trap_template_v3; @@ -669,285 +586,253 @@ sub node_to_trapitem { else { $template = $template || \%trap_template_v2; } - + # Create item hash - my $item = { %{$template} }; - - $item->{name} = "SNMP Trap: $node->{ moduleID }::$node->{ label }"; - + my $item = { %{ $template } }; + + $item->{ name } = "SNMP Trap: $node->{ moduleID }::$node->{ label }"; + # Merge in item defaults - %{$item} = ( %{$template}, %{$item} ); - + %{ $item } = (%{ $template }, %{ $item } ); + # Create trap key - my $oid = $node->{objectID}; + my $oid = $node->{ objectID }; $oid =~ s/\./\\./g; - $item->{key} = "snmptrap[\"\\s$oid\\s\"]"; - + $item->{ key } = "snmptrap[\"\\s$oid\\s\"]"; + # Parse item desciption my $desc = ''; - if ( $node->{description} ) { - $desc = $node->{description}; - $desc =~ s/^\s+|\s+$|\n//g; # Trim left/right whitespace and newlines - $desc =~ s/\s{2,}/ /g; # Remove padding + if ($node->{ description }) { + $desc = $node->{ description }; + $desc =~ s/^\s+|\s+$|\n//g; # Trim left/right whitespace and newlines + $desc =~ s/\s{2,}/ /g; # Remove padding } - + # Append varbinds to description - if ( defined( $node->{varbinds} ) && scalar @{ $node->{varbinds} } ) { - my $varcount = scalar @{ $node->{varbinds} }; - - if ( $desc ne '' ) { + if (defined($node->{ varbinds }) && scalar @{ $node->{ varbinds } }) { + my $varcount = scalar @{ $node->{ varbinds } }; + + if ($desc ne '') { $desc .= "\n\n"; } - + $desc .= "Varbinds:\n"; - - for ( my $i = 0 ; $i < $varcount ; $i++ ) { - my $varbind_label = $node->{varbinds}[$i]; - $desc .= "$i. $varbind_label"; - + + for(my $i = 0; $i < $varcount; $i++) { + my $varbind_label = $node->{ varbinds }[$i]; + $desc .= "$i. $varbind_label"; + # Try to find OID for each varbind my $varbind_path = "$node->{ moduleID }::$varbind_label"; - my $varbind = $SNMP::MIB{$varbind_path}; - - if ( defined($varbind) ) { - $desc .= " ($varbind->{ type })\n" if $varbind->{type}; - - if ( $varbind->{description} ) { - my $vbdesc = $varbind->{description}; - $vbdesc =~ - s/[ \t]+/ /g; # Replace long whitespace with single space - $vbdesc =~ - s/^ ?/ /mg; # Prepend indent to each description line - $desc .= "$vbdesc\n\n"; + my $varbind = $SNMP::MIB{ $varbind_path }; + + if (defined($varbind)) { + $desc .= " ($varbind->{ type })\n" if $varbind->{ type }; + + if ($varbind->{ description }) { + my $vbdesc = $varbind->{ description }; + $vbdesc =~ s/[ \t]+/ /g; # Replace long whitespace with single space + $vbdesc =~ s/^ ?/ /mg; # Prepend indent to each description line + $desc .= "$vbdesc\n\n"; } - } - else { + } else { $desc .= "\n"; } } } - $item->{description} = $desc; - + $item->{ description } = $desc; + return $item; } =head2 node_is_current - Parameters : SNMP::MIB::Node $node Returns : (int) 0|1 Description : Returns true if the specified OID is not obsolete - =cut - sub node_is_current { my ($node) = @_; - - return ( node_is_valid_trap($node) - || ( defined( $node->{status} ) && $node->{status} ne 'Obsolete' ) ); + + return ( + node_is_valid_trap($node) + || (defined($node->{ status }) && $node->{ status } ne 'Obsolete') + ); } =head2 node_is_valid_scalar - Parameters : SNMP::MIB::Node $node Returns : (int) 0|1 Description : Returns true if the specified OID is current, readable and defines a valid value type. - =cut - sub node_is_valid_scalar { my ($node) = @_; - + return ( - node_is_current($node) - && $node->{type} - && ( - $node->{type} eq 'NOTIF' - || $node->{type} eq 'TRAP' - || ( $node->{access} eq 'ReadOnly' - || $node->{access} eq 'ReadWrite' ) - ) - + node_is_current($node) + && $node->{ type } + && ( + $node->{ type } eq 'NOTIF' || $node->{ type } eq 'TRAP' + || ($node->{ access } eq 'ReadOnly' || $node->{ access } eq 'ReadWrite') + ) + ); } =head2 node_is_valid_trap - Parameters : SNMP::MIB::Node $node Returns : (int) 0|1 Description : Returns true if the specified OID is an SNMP Trap - =cut - sub node_is_valid_trap { my ($node) = @_; - - return ( defined( $node->{type} ) - && ( $node->{type} eq 'NOTIF' || $node->{type} eq 'TRAP' ) ); + + return ( + defined($node->{ type }) && ($node->{ type } eq 'NOTIF' || $node->{ type } eq 'TRAP') + ); } =head2 node_is_valid_table - Parameters : SNMP::MIB::Node $node Returns : (int) 0|1 Description : Returns true if the specified OID is a valid table which is current, readable and contains a single child (row definition) - =cut - sub node_is_valid_table { my ($node) = @_; - + # The MIB will define a 'SEQUENCE OF' attribute for tables but # SNMP::MIB::NODE does not expose this value. Instead, a table # node must be 'NoAccess' and have a single 'NoAccess' child return ( node_is_current($node) - - # Table is NoAccess - && $node->{access} eq 'NoAccess' - - # Table has one child (row definition) - && ( scalar @{ $node->{children} } ) == 1 - - # Table row is NoAccess - && $node->{children}[0]->{access} eq 'NoAccess' - - # Table row defines atleast one index - && ( scalar @{ $node->{children}[0]->{indexes} } ) + + # Table is NoAccess + && $node->{ access } eq 'NoAccess' + + # Table has one child (row definition) + && (scalar @{ $node->{ children } }) == 1 + + # Table row is NoAccess + && $node->{ children }[0]->{ access } eq 'NoAccess' + + # Table row defines atleast one index + && (scalar @{ $node->{ children }[0]->{ indexes } }) ); } =head2 build_template - Parameters : (hash) $template SNMP::MIB::NODE $node Returns : (void) Description : Traverses a loaded MIB tree from the specified OID node a populates a Zabbix Template hash with items, discovery rules, item prototypes, groups and macros. - =cut - sub build_template { - my ( $template, $node ) = @_; - + my ($template, $node) = @_; + # Ignore obsolete OIDs - if ( node_is_current($node) ) { - + if (node_is_current($node)) { # Create an Item Application name for this node my $appname = "$node->{ moduleID }::$node->{ parent }->{ label }"; - + # Is this a scalar value OID? - if ( node_is_valid_trap($node) ) { - + if (node_is_valid_trap($node)) { # Convert the SNMP::MIB::Node to a Zabbix Template SNMP Trap Item my $item = node_to_trapitem($node); - - # Add item applications to template application list - $item->{applications} = [ { name => $appname } ]; - $template->{apptags}->{$appname} = 1; + + # Add item applications to template application list + $item->{ applications } = [{ name => $appname }]; + $template->{ apptags }->{ $appname } = 1; # Add item to template - push( @{ $template->{items} }, $item ); - + push(@{ $template->{ items } }, $item ); + # If the snmptrap has children. - foreach ( @{ $node->{children} } ) { + foreach(@{ $node->{ children } }) { - # Convert the SNMP::MIB::Node to a Zabbix Template SNMP Trap Item + # Convert the SNMP::MIB::Node to a Zabbix Template SNMP Trap Item my $item = node_to_trapitem($_); # Add item applications to template application list - $item->{applications} = [ { name => $appname } ]; - $template->{apptags}->{$appname} = 1; + $item->{ applications } = [{ name => $appname }]; + $template->{ apptags }->{ $appname } = 1; # Add item to template - push( @{ $template->{items} }, $item ); + push(@{ $template->{ items } }, $item ); } - - } - elsif ( node_is_valid_scalar($node) ) { - + + } elsif (node_is_valid_scalar($node)) { + # Convert the SNMP::MIB::Node to a Zabbix Template Item hash my $item = node_to_item($node); - + # Append '.0' to normal SNMP OIDS - $item->{snmp_oid} = "$item->{ snmp_oid }.0"; - - # Add item applications to template application list - $item->{applications} = [ { name => $appname } ]; - $template->{apptags}->{$appname} = 1; + $item->{ snmp_oid } = "$item->{ snmp_oid }.0"; + + # Add item applications to template application list + $item->{ applications } = [{ name => $appname }]; + $template->{ apptags }->{ $appname } = 1; # Add item to template - push( @{ $template->{items} }, $item ); - - } - elsif ( node_is_valid_table($node) ) { + push(@{ $template->{ items } }, $item ); + } elsif (node_is_valid_table($node)) { # Get row OID my $table = $node; - my $row = $node->{children}[0]; - + my $row = $node->{ children }[0]; + # Validate naming standard - if ( $table->{label} !~ /Table/ ) { - print STDERR -"Warning: $table->{ moduleID }:: $table->{ label } appears to be a table but does not have the 'Table' suffix\n"; + if ($table->{ label } !~ /Table/) { + print STDERR "Warning: $table->{ moduleID }:: $table->{ label } appears to be a table but does not have the 'Table' suffix\n"; } - - if ( $row->{label} !~ /Entry/ ) { - print STDERR -"Warning: $row->{ moduleID }:: $row->{ label } appears to be a table entry but does not have the 'Entry; suffix\n"; + + if ($row->{ label } !~ /Entry/) { + print STDERR "Warning: $row->{ moduleID }:: $row->{ label } appears to be a table entry but does not have the 'Entry; suffix\n"; } - + # This is a table. Build a discovery rule my $disc_rule = {}; - $disc_rule = node_to_item( $row, \%disc_rule_template ); - + $disc_rule = node_to_item($row, \%disc_rule_template); + # Update discovery rule name - $disc_rule->{name} = "$disc_rule->{ name } Discovery"; - $disc_rule->{snmp_oid} = "discovery["; + $disc_rule->{ name } = "$disc_rule->{ name } Discovery"; + $disc_rule->{ snmp_oid } = "discovery["; # find any *Descr column my $index = '{#SNMPINDEX}'; - foreach my $column ( @{ $row->{children} } ) { - if ( node_is_valid_scalar($column) ) { - if ( $column->{label} =~ m/Descr$/ ) { - $disc_rule->{snmp_oid} .= - "{#SNMPVALUE},$column->{ objectID },"; + foreach my $column(@{ $row->{ children } }) { + if (node_is_valid_scalar($column)) { + if($column->{ label } =~ m/Descr$/) { + $disc_rule->{ snmp_oid } .= "{#SNMPVALUE},$column->{ objectID },"; $index = '{#SNMPVALUE}'; } } } - 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 - foreach my $column ( @{ $row->{children} } ) { - if ( node_is_valid_scalar($column) ) { - my $new_snmp_oid = - $disc_rule->{snmp_oid} . "{#" - . uc( $column->{label} ) . "}," - . $column->{objectID} . ","; - if ( length($new_snmp_oid) <= 255 ) { - $disc_rule->{snmp_oid} = $new_snmp_oid; + 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 + foreach my $column(@{ $row->{ children } }) { + if (node_is_valid_scalar($column)) { + my $new_snmp_oid = $disc_rule->{ snmp_oid } . "{#" . uc($column->{ label }) . "}," . $column->{ objectID } . ","; + if (length($new_snmp_oid) <= 255) { + $disc_rule->{ snmp_oid } = $new_snmp_oid; } } } - $disc_rule->{snmp_oid} = - substr( $disc_rule->{snmp_oid}, 0, -1 ) . "]"; - } + $disc_rule->{ snmp_oid } = substr($disc_rule->{ snmp_oid }, 0, -1) . "]"; + } else { - - # find entry index colum + # 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"; + #print STDERR + #"Warning: $row->{ moduleID }:: $row->{ label }:: $column->{label} $column->{ objectID }, Index Found\n"; $disc_rule->{snmp_oid} = $column->{objectID}; } } @@ -955,48 +840,37 @@ sub build_template { } # Fetch an arbitrary column OID for Zabbix to use for discovery - my $index_oid = $row->{children}[0]; - if ( !defined($index_oid) ) { - print STDERR -"No index found for table $table->{ moduleID}::$table->{ label } ($table->{ objectID })\n"; - } - else { - + my $index_oid = $row->{ children }[0]; + if (!defined($index_oid)) { + print STDERR "No index found for table $table->{ moduleID}::$table->{ label } ($table->{ objectID })\n"; + } else { # Remove unrequired fields - delete( $disc_rule->{applications} ); - delete( $disc_rule->{data_type} ); - + delete($disc_rule->{ applications }); + delete($disc_rule->{ data_type }); + # Create new array for prototypes - $disc_rule->{item_prototypes} = []; - + $disc_rule->{ item_prototypes } = []; + # Add prototypes for each row column - foreach my $column ( @{ $row->{children} } ) { - if ( node_is_valid_scalar($column) ) { - if ( my $proto = - node_to_item( $column, \%item_proto_template ) ) - { - $proto->{name} = "$proto->{ name } for $index"; - $proto->{key} = "$column->{ label }\[$index]"; - $proto->{snmp_oid} = - "$proto->{ snmp_oid }.{#SNMPINDEX}"; - - # Add item applications to template application list - $proto->{applications} = [ { name => $appname } ]; - $template->{apptags}->{$appname} = 1; + foreach my $column(@{ $row->{ children } }) { + if (node_is_valid_scalar($column)) { + if (my $proto = node_to_item($column, \%item_proto_template)) { + $proto->{ name } = "$proto->{ name } for $index"; + $proto->{ key } = "$column->{ label }\[$index]"; + $proto->{ snmp_oid } = "$proto->{ snmp_oid }.{#SNMPINDEX}"; + + # Add item applications to template application list + $proto->{ applications } = [{ name => $appname }]; + $template->{ apptags }->{ $appname } = 1; if ( $opts->{zabbix_ver} == 3 ) { - push( - @{ $disc_rule->{item_prototypes} }, - $proto - ); + push(@{ $disc_rule->{ item_prototypes } }, $proto); } else { + # No need for Indexer to be added in Zabbix 2.4 + if ( $proto->{name} !~ m/Index/ ) { - if ( $proto->{name} !~ m/Index/ ) { - push( - @{ $disc_rule->{item_prototypes} }, - $proto - ); + push(@{ $disc_rule->{ item_prototypes } }, $proto); } } } @@ -1004,16 +878,13 @@ sub build_template { } # Add discovery rule to template - push( @{ $template->{discovery_rules} }, $disc_rule ); - + push(@{ $template->{ discovery_rules } }, $disc_rule); } } - } - else { - + } else { # Parse children - foreach ( @{ $node->{children} } ) { - build_template( $template, $_ ); + foreach(@{ $node->{ children } }) { + build_template($template, $_); } } } @@ -1023,152 +894,131 @@ $SNMP::save_descriptions = 1; SNMP::initMib(); # Verify the specified OID exists -if ( $opts->{oid} !~ m/^\./ ) { - $opts->{oid} = "." . $opts->{oid}; +if ($opts->{ oid } !~ m/^\./) { + $opts->{ oid } = "." . $opts->{ oid } } -my $oid_root = $SNMP::MIB{ $opts->{oid} }; -if ( !$oid_root || $oid_root->{objectID} ne $opts->{oid} ) { +my $oid_root = $SNMP::MIB{ $opts->{ oid } }; +if (!$oid_root || $oid_root->{ objectID } ne $opts->{ oid }) { print STDERR "OID $opts->{ oid } not found in MIB tree.\n"; exit 1; - # Build a Zabbix template -} -else { - my $suffix = $opts->{snmpver} > 2 ? " v$opts->{ snmpver }" : ''; - my $template_name = $opts->{name} - || "Template $oid_root->{ moduleID } - $oid_root->{ label }$suffix"; - my $template = { +# Build a Zabbix template +} else { + my $suffix = $opts->{ snmpver } > 2 ? " v$opts->{ snmpver }" : ''; + my $template_name = $opts->{ name } || "Template $oid_root->{ moduleID } - $oid_root->{ label }$suffix"; + my $template = { name => $template_name, template => $template_name, description => "Generated by mib2zabbix", apptags => {}, applications => [], discovery_rules => [], - groups => [ { name => $opts->{group} } ], + groups => [{ + name => $opts->{ group } + }], items => [], - macros => [ + macros => [ { macro => '{$MIB2ZABBIX_CMD}', value => $cmd }, - { macro => '{$OID}', value => "$oid_root->{ objectID }" }, - { macro => '{$OID_PATH}', value => oid_path($oid_root) }, - { macro => '{$OID_MOD}', value => $oid_root->{moduleID} }, - { macro => '{$SNMP_PORT}', value => $opts->{snmpport} } + { macro => '{$OID}', value => "$oid_root->{ objectID }" }, + { macro => '{$OID_PATH}', value => oid_path($oid_root) }, + { macro => '{$OID_MOD}', value => $oid_root->{ moduleID } }, + { macro => '{$SNMP_PORT}', value => $opts->{ snmpport } } ] }; # Add SNMP connection macros - if ( $opts->{snmpver} < 3 ) { - push( - @{ $template->{macros} }, - { macro => '{$SNMP_COMMUNITY}', value => $opts->{snmpcomm} } - ); - } - elsif ( $opts->{snmpver} == 3 ) { - push( - @{ $template->{macros} }, - { macro => '{$SNMP_USER}', value => $opts->{v3user} } - ); - push( - @{ $template->{macros} }, - { macro => '{$SNMP_CONTEXT}', value => $opts->{v3context} } - ); - push( - @{ $template->{macros} }, - { macro => '{$SNMP_AUTHPASS}', value => $opts->{v3auth_pass} } - ); - push( - @{ $template->{macros} }, - { macro => '{$SNMP_PRIVPASS}', value => $opts->{v3sec_pass} } - ); - } - build_template( $template, $oid_root, 0 ); - + if($opts->{ snmpver } < 3) { + push(@{ $template->{ macros } }, { macro => '{$SNMP_COMMUNITY}', value => $opts->{ snmpcomm } }); + } elsif($opts->{ snmpver } == 3) { + push(@{ $template->{ macros } }, { macro => '{$SNMP_USER}', value => $opts->{ v3user } }); + push(@{ $template->{ macros } }, { macro => '{$SNMP_CONTEXT}', value => $opts->{ v3context } }); + push(@{ $template->{ macros } }, { macro => '{$SNMP_AUTHPASS}', value => $opts->{ v3auth_pass } }); + push(@{ $template->{ macros } }, { macro => '{$SNMP_PRIVPASS}', value => $opts->{ v3sec_pass } }); + }; + build_template($template, $oid_root, 0); + # Convert applications hash to array - @{ $template->{applications} } = - map { { name => $_ } } keys %{ $template->{apptags} }; - delete( $template->{apptags} ); + @{ $template->{ applications } } = map { { name => $_ } } keys %{ $template->{ apptags } }; + delete($template->{ apptags }); # Build XML document my $time = time(); - # version3 + # version 3 my $output_v3 = { - version => '3.0', - date => time2str( "%Y-%m-%dT%H:%M:%SZ", $time ), - groups => $template->{groups}, - templates => [$template], - triggers => [], - graphs => [], - value_maps => [$valuemaps] + version => '3.0', + date => time2str("%Y-%m-%dT%H:%M:%SZ", $time), + groups => $template->{ groups }, + templates => [$template], + triggers => [], + graphs => [], + 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 => [] + version => '2.0', + date => time2str( "%Y-%m-%dT%H:%M:%SZ", $time ), + groups => $template->{groups}, + templates => [$template], + triggers => [], + graphs => [] }; # Output stream my $fh = *STDOUT; - if ( $opts->{filename} ) { - open( $fh, ">$opts->{ filename }" ) or die "$!"; - } - + if ($opts->{ filename }) { + open($fh, ">$opts->{ filename }") or die "$!"; + } + # Output XML if ( $opts->{zabbix_ver} == 3 ) { - - XMLout( - $output_v3, - OutputFile => \$fh, - XMLDecl => "", - 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', - 'value_maps' => %{$valuemaps} ? 'value_map' : undef, - 'mappings' => 'mapping' + XMLout($output_v3, + OutputFile => \$fh, + XMLDecl => "", + 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', + 'value_maps' => %{ $valuemaps } ? 'value_map' : undef, + 'mappings' => 'mapping' } ); } else { - XMLout( - $output_v2, - OutputFile => \$fh, - XMLDecl => "", - 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' + XMLout($output_v2, + OutputFile => \$fh, + XMLDecl => "", + 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; } }