Skip to content

Instantly share code, notes, and snippets.

@peelman
Last active April 14, 2025 02:08
Show Gist options
  • Save peelman/d6569a0691c7118ffc762010e918d554 to your computer and use it in GitHub Desktop.
Save peelman/d6569a0691c7118ffc762010e918d554 to your computer and use it in GitHub Desktop.
Nokia SFP Change Trap Handler

Nokia SFP Change Trap Handler

Posted mostly for inspiration.

Installation

  1. Copy nokia_sfp_changed.rb to /usr/local/bin (or wherever you store scripts on your system(s).
  2. Be sure the following Gems are installed: optparse, slack-notifier, snmp

Configuration

SNMPtt

/etc/snmp/snmptt.ini (Debian/Ubuntu Location, YMMV)

[TrapFiles]
# A list of snmptt.conf files (this is NOT the snmptrapd.conf file).  The COMPLETE path 
# and filename.  Ex: '/etc/snmp/snmptt.conf'
# /etc/snmp/traps.d/nokia-traps.conf
#
snmptt_conf_files = <<END
/etc/snmp/traps.d/nokia-traps.conf
END

/etc/snmp/traps.d/nokia-traps.conf

...
EVENT tmnxEqPortSFPInserted .1.3.6.1.4.1.6527.3.1.3.2.2.0.8 "Status Events" Normal
FORMAT Generated when an SFF is inserted in the port. $*
EXEC /usr/local/bin/nokia_sfp_changed.rb -h $A -c <yourcommunitystring> -p $1 -i
SDESC
Generated when an SFF is inserted in the port.
Variables:
  1: tmnxPortNotifyPortId
EDESC
#
#
#
EVENT tmnxEqPortSFPRemoved .1.3.6.1.4.1.6527.3.1.3.2.2.0.9 "Status Events" Normal
FORMAT Generated when an SFF is removed from the port. $*
EXEC /usr/local/bin/nokia_sfp_changed.rb -h $A -c <yourcommunitystring> -p $1 -r
SDESC
Generated when an SFF is removed from the port.
Variables:
  1: tmnxPortNotifyPortId
EDESC
...

Sample output

image image

#!/usr/bin/env ruby
######################################################################################################
#
# Description:
# Handle SNMP Traps for Nokia SFP Changes
# * Post All Traps to Slack Channel provided by SLACK_WEBHOOK_URL
#
######################################################################################################
#
# Author: Nick Peelman
#
######################################################################################################
#
# Usage:
# nokia_sfp_changed.rb -h <hostname> -c <community> -p <index> [-i|-r]"
# Parameters:
# * <hostname>: Hostname that sent the trap
# * <community>: SNMP Community with Read privileges to the IF-MIB
# * <index>: the index of the interface that send the event
#
######################################################################################################
#
# Requirements
# * gem install slack-notifier
# * gem install snmp
#
######################################################################################################
require 'optparse'
require 'slack-notifier'
require 'snmp'
######################################################################################################
# CONFIGURATION Parameters
#
SLACK_WEBHOOK_URL = ""
SLACK_CHANNEL = "#port-notifications"
######################################################################################################
@oid_sysname = SNMP::ObjectName.new "1.3.6.1.2.1.1.5.0"
@oid_port_id_schema = SNMP::ObjectName.new "1.3.6.1.4.1.6527.3.1.2.2.1.3.1.32.1"
@oid_sfp_type = SNMP::ObjectName.new "1.3.6.1.4.1.6527.3.1.2.2.4.2.1.46.1"
@oid_ifname = SNMP::ObjectName.new "1.3.6.1.2.1.31.1.1.1.1"
@oid_array = [
@oid_sysname,
@oid_port_id_schema,
@oid_sfp_type,
@oid_ifname
]
@sysname = ''
@port_scheme = 0
@sfp_type = ''
@ifname = ''
def parse_args(args = {})
@print = args[:print].nil? ? true : args[:print]
@exit = args[:exit].nil? ? true : args[:exit]
# now, handle the arguments...
@opts = OptionParser.new
@opts.on("-h", "--hostname HOSTNAME", "Hostname") do |h|
@hostname = h
end
@opts.on("-c", "--community COMMUNITY", "snmp community") do |c|
@community = c
end
@opts.on("-p", "--port PORTID", "Port ID") do |p|
@port_id = p
end
@opts.on("-r", "--removed", "SFP Removed") do |r|
@removed = true
end
@opts.on("-i", "--inserted", "SFP Inserted") do |i|
@inserted = true
end
@opts.on("-d", "--debug", "print output, don't send to slack") do |d|
@debug = true
end
@opts.on_tail("-h", "--help", "Show this message") do
puts @opts
exit
end
@opts.parse!
end
def bin_to_int(array)
array.join('').to_i(2)
end
def safe_vb_to_int(number, safe = 0)
Integer(number) rescue safe
end
def fetch_oids(host, community)
SNMP::Manager.open(host: host, community: community) do |manager|
response = manager.get(@oid_array)
response.each_varbind do |vb|
case vb.name.to_str
when @oid_sysname.to_str
@sysname = vb.value
when @oid_port_id_schema.to_str
@port_scheme = safe_vb_to_int(vb.value)
when @oid_sfp_type.to_str
@sfp_type = vb.value
when @oid_ifname.to_str
@ifname = vb.value
else
puts "Error: unknown VarBind returned: #{vb}"
end
end
end
end
def send_slack_message(message, attachments)
notifier = Slack::Notifier.new SLACK_WEBHOOK_URL
notifier.post({text:"#{message}", attachments: attachments})
end
def main
parse_args
@oid_sfp_type.push(@port_id)
@oid_ifname.push(@port_id)
fetch_oids(@hostname, @community)
@msgcolor = "#cccccc"
@emoji = ':black_square_button:'
if @inserted
@state = "Inserted"
@msgcolor = 'good'
@emoji = ":large_green_circle:"
elsif @removed
@state = "Removed"
@msgcolor = 'warning'
@emoji = ":large_yellow_circle:"
else
@state = "Unknown"
end
message = "#{@emoji} SFP Changed: #{@hostname} - Port: #{@ifname} - #{@state}"
attachments = [{
'color': "#{@msgcolor}",
'fallback': message,
'fields': [
{
'title': "Device",
'value': "#{@hostname}",
'short': true
},
{
'title': "Port",
'value': "#{@ifname}",
'short': true
},
{
'title': "SFP",
'value': "#{@state}",
'short': true
},
{
'title': "SFP Type",
'value': "#{@sfp_type}",
'short': true
}
]
}]
puts attachments if @debug
send_slack_message('', attachments) unless @debug
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment