app/models/miq_snmp.rb
require 'snmp'
class MiqSnmp
include Vmdb::Logging
AVAILABLE_TYPES_HASH = {
"Null" => SNMP::Null,
"Integer" => SNMP::Integer,
"Unsigned32" => SNMP::Unsigned32,
"OctetString" => SNMP::OctetString,
"ObjectId" => SNMP::ObjectId,
"ObjectName" => SNMP::ObjectName,
"IpAddress" => SNMP::IpAddress,
"Counter32" => SNMP::Counter32,
"Counter64" => SNMP::Counter64,
"Gauge32" => SNMP::Gauge32,
"TimeTicks" => SNMP::TimeTicks
}
def self.trap_v1(inputs)
_log.info(">> inputs=#{inputs.inspect}")
host = inputs[:host] || inputs['host']
port = inputs[:port] || inputs['port'] || 162
# The enterprise OID from the IANA assigned numbers (www.iana.org/assignments/enterprise-numbers) as a String or an ObjectId.
enterprise = inputs[:enterprise] || inputs['enterprise'] || enterprise_oid_string
raise MiqException::Error, _("MiqSnmp.trap_v1: Ensure that enterprise OID is provided") if enterprise.nil?
# The IP address of the SNMP agent as a String or IpAddress.
address = inputs[:agent_address] || inputs['agent_address'] || agent_address
if address.nil?
raise MiqException::Error,
_("MiqSnmp.trap_v1: Ensure that server.host is configured properly in your settings.yml file")
end
# An integer respresenting the number of hundredths of a second that this system has been up.
uptime = inputs[:sysuptime] || inputs['sysuptime'] || system_uptime
# The generic trap identifier. One of :coldStart, :warmStart, :linkDown, :linkUp, :authenticationFailure, :egpNeighborLoss, or :enterpriseSpecific
generic_trap = inputs[:generic_trap] || inputs['generic_trap']
generic_trap = generic_trap.to_sym unless generic_trap.nil?
generic_trap = :enterpriseSpecific unless [:coldStart, :warmStart, :linkDown, :linkUp, :authenticationFailure, :egpNeighborLoss, :enterpriseSpecific].include?(generic_trap)
# An integer representing the specific trap type for an enterprise-specific trap.
specific_trap = inputs[:specific_trap] || inputs['specific_trap']
if specific_trap.nil? && generic_trap == :enterpriseSpecific
raise MiqException::Error, _("MiqSnmp.trap_v1: Ensure that specific trap is provided")
end
# A list of additional varbinds to send with the trap.
object_list = inputs[:object_list] || inputs['object_list'] || []
vars = create_var_bind_list(object_list)
hosts = host.kind_of?(Array) ? host : [host]
hosts.each do |lhost|
_log.info("Sending SNMP Trap (v1) to host=[#{lhost}], port=[#{port}], enterprise_id=[#{enterprise}], generic_trap=[#{generic_trap}], specific_trap=[#{specific_trap}], uptime=[#{uptime}], agent=[#{agent_address}], vars=#{vars.inspect}")
SNMP::Manager.open(:Host => lhost, :TrapPort => port) do |manager|
manager.trap_v1(enterprise, agent_address, generic_trap, specific_trap, uptime, vars)
end
end
end
def self.trap_v2(inputs)
_log.info(">> inputs=#{inputs.inspect}")
host = inputs[:host] || inputs['host']
port = inputs[:port] || inputs['port'] || 162
# An integer respresenting the number of hundredths of a second that this system has been up.
uptime = inputs[:sysuptime] || inputs['sysuptime'] || system_uptime
# trap_oid: An ObjectId or String with the OID identifier for this trap.
trap_oid = inputs[:trap_oid] || inputs['trap_oid']
raise MiqException::Error, _("MiqSnmp.trap_v2: Ensure that a trap object id is provided") if trap_oid.nil?
trap_oid = subst_oid(trap_oid)
# A list of additional varbinds to send with the trap.
object_list = inputs[:object_list] || inputs['object_list'] || []
vars = create_var_bind_list(object_list, trap_oid)
hosts = host.kind_of?(Array) ? host : [host]
hosts.each do |lhost|
_log.info("Sending SNMP Trap (v2) to host=[#{lhost}], port=[#{port}], trap_oid=[#{trap_oid}], vars=#{vars.inspect}")
SNMP::Manager.open(:Host => lhost, :TrapPort => port) do |manager|
manager.trap_v2(uptime, trap_oid, vars)
end
end
end
# IANA assigned Private Enterprise Number 33482 to ManageIQ
def self.enterprise_oid_string
@@enterprise_oid_string ||= "1.3.6.1.4.1.33482"
end
def self.enterprise_oid
@@enterprise_oid ||= SNMP::ObjectId.new(enterprise_oid_string)
end
def self.available_types
AVAILABLE_TYPES_HASH.keys
end
def self.create_var_bind_list(object_list, base = nil)
vars = []
object_list.each do |tuple|
oid = subst_oid(tuple[:oid], base)
value = tuple[:value]
type = tuple[:type] || tuple[:var_type]
snmpType = AVAILABLE_TYPES_HASH[type]
snmpVal = (snmpType == SNMP::Null) ? SNMP::Null.new : snmpType.new(value)
vars << SNMP::VarBind.new(oid, snmpVal)
end
vars
end
private_class_method :create_var_bind_list
def self.subst_oid(oid, base = nil)
oid = oid.strip
# Set base to our enterprise oid, if uninitialize
base = enterprise_oid_string if base.nil?
# If it begins with a dot, append it to the base
return "#{base}#{oid}" if oid[0, 1] == "."
# Need to move these to ManageIQ MIB
case oid.downcase
when "info" then "#{enterprise_oid_string}.1"
when "warn", "warning" then "#{enterprise_oid_string}.2"
when "crit", "critical", "error" then "#{enterprise_oid_string}.3"
when "description" then "#{base}.1"
when "category" then "#{base}.2"
when "message" then "#{base}.3"
when "object" then "#{base}.4"
when "location" then "#{base}.5"
when "platform" then "#{base}.6"
when "url" then "#{base}.7"
when "source" then "#{base}.8"
when "custom1" then "#{base}.9"
when "custom2" then "#{base}.10"
else oid
end
end
private_class_method :subst_oid
def self.system_uptime
(Time.now.utc - MiqServer.my_server.started_on.utc) * 100
end
private_class_method :system_uptime
def self.agent_address
Settings.server.host
end
private_class_method :agent_address
end