|  | #!/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 |