Module: Arborist::Monitor::SNMP

Extended by:
Configurability, Loggability
Included in:
CPU, Disk, Memory, Process, UPS, UPS::Battery
Defined in:
lib/arborist/monitor/snmp.rb

Overview

SNMP checks for Arborist. Requires an SNMP agent to be installed on target machine, and the various “pieces” enabled for your platform.

For example, for disk monitoring with Net-SNMP, you’ll want to set ‘includeAllDisks’ in the snmpd.conf. bsnmpd on FreeBSD benefits from the ‘bsnmp-ucd’ package. Etc.

Constant Summary collapse

USED_PROPERTIES =

Always request the node addresses and any config.

[ :addresses, :config ].freeze
IDENTIFICATION_OID =

The OID that returns the system environment.

'1.3.6.1.2.1.1.1.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#identifiersObject (readonly)

The mapping of addresses back to node identifiers.



42
43
44
# File 'lib/arborist/monitor/snmp.rb', line 42

def identifiers
  @identifiers
end

#resultsObject (readonly)

The results hash that is sent back to the manager.



45
46
47
# File 'lib/arborist/monitor/snmp.rb', line 45

def results
  @results
end

Instance Method Details

#run(nodes) ⇒ Object

Connect to the SNMP daemon and yield.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/arborist/monitor/snmp.rb', line 50

def run( nodes )

  # Create mapping of addresses back to node identifiers,
  # and retain any custom (overrides) config per node.
  #
  @identifiers = {}
  @results     = {}
  nodes.each_pair do |(identifier, props)|
    next unless props.key?( 'addresses' )
    address = props[ 'addresses' ].first
    self.identifiers[ address ] = [ identifier, props ]
  end

  # Perform the work!
  #
  mainstart  = Time.now
  threads    = ThreadGroup.new
  batchcount = nodes.size / Arborist::Monitor::SNMP.batchsize
  self.log.debug "Starting SNMP run for %d nodes" % [ nodes.size ]

  self.identifiers.keys.each_slice( Arborist::Monitor::SNMP.batchsize ).each_with_index do |slice, batch|
    slicestart = Time.now
    self.log.debug "  %d hosts (batch %d of %d)" % [
      slice.size,
      batch + 1,
      batchcount + 1
    ]

    slice.each do |host|
      thr = Thread.new do
        config = self.identifiers[ host ].last || {}
        opts = {
          host:      host,
          port:      config[ 'port' ]      || Arborist::Monitor::SNMP.port,
          version:   config[ 'version' ]   || Arborist::Monitor::SNMP.version,
          community: config[ 'community' ] || Arborist::Monitor::SNMP.community,
          timeout:   config[ 'timeout' ]   || Arborist::Monitor::SNMP.timeout,
          retries:   config[ 'retries' ]   || Arborist::Monitor::SNMP.retries
        }

        begin
          NETSNMP::Client.new( opts ) do |snmp|
            Thread.current[ :system ] = snmp.get( oid: IDENTIFICATION_OID )
            yield( host, snmp )
          end

        rescue => err
          self.log.error "%s: %s\n%s" % [ host, err.message, err.backtrace.join("\n  ") ]
          self.results[ host ] = {
            error: "Exception (%s: %s)" % [ err.class.name, err.message ]
          }
        end
      end

      threads.add( thr )
    end

    # Wait for thread completions
    threads.list.map( &:join )
    self.log.debug "  finished after %0.1f seconds." % [ Time.now - slicestart ]
  end
  self.log.debug "Completed SNMP run for %d nodes after %0.1f seconds." % [ nodes.size, Time.now - mainstart ]

  # Map everything back to identifier -> attribute(s), and send to the manager.
  #
  reply = self.results.each_with_object({}) do |(address, results), hash|
    identifier = self.identifiers[ address ] or next
    hash[ identifier.first ] = results
  end
  return reply

ensure
  @identifiers = {}
  @results     = {}
end

#systemObject

Return the current SNMP connection system string.



128
129
130
# File 'lib/arborist/monitor/snmp.rb', line 128

def system
  return Thread.current[ :system ]
end