arborist-snmp 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/arborist/monitor/snmp.rb +14 -20
- data/lib/arborist/monitor/snmp/cpu.rb +7 -11
- data/lib/arborist/monitor/snmp/disk.rb +35 -17
- data/lib/arborist/monitor/snmp/memory.rb +6 -6
- data/lib/arborist/monitor/snmp/process.rb +28 -12
- data/lib/arborist/snmp.rb +2 -2
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a1e7f51762b179cee87fda4bc23a7f8e5875cf5
|
4
|
+
data.tar.gz: e4455394ab0a4e0f5affa2aba4053ec915585dad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61225e9bd9a10ae9ede1072b30dda70fb93910b2f1210e67d60c368ace730aaebe1ae0ee8b3fadf9ce5e1d85ec33b5970be12d6f0c262def2dc18ef4cf7b2d64
|
7
|
+
data.tar.gz: a725b24835f6d7a9eabd04c7ea36a4fe8ecbdbaab2a3863021aa28d125e1969009b1e8f8d569e42b89586bdbb4137010dbad9d8012b3b98e26c97c64922f0a4e
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#encoding: utf-8
|
4
4
|
|
5
5
|
require 'arborist/monitor' unless defined?( Arborist::Monitor )
|
6
|
-
require '
|
6
|
+
require 'netsnmp'
|
7
7
|
|
8
8
|
# SNMP checks for Arborist. Requires an SNMP agent to be installed
|
9
9
|
# on target machine, and the various "pieces" enabled for your platform.
|
@@ -38,13 +38,6 @@ module Arborist::Monitor::SNMP
|
|
38
38
|
setting :batchsize, default: 25
|
39
39
|
end
|
40
40
|
|
41
|
-
# Indicate to FFI that we're using threads.
|
42
|
-
Net::SNMP.thread_safe = true
|
43
|
-
|
44
|
-
|
45
|
-
# The system type, as advertised.
|
46
|
-
attr_reader :system
|
47
|
-
|
48
41
|
# The mapping of addresses back to node identifiers.
|
49
42
|
attr_reader :identifiers
|
50
43
|
|
@@ -86,7 +79,7 @@ module Arborist::Monitor::SNMP
|
|
86
79
|
thr = Thread.new do
|
87
80
|
config = self.identifiers[ host ].last || {}
|
88
81
|
opts = {
|
89
|
-
|
82
|
+
host: host,
|
90
83
|
port: config[ 'port' ] || Arborist::Monitor::SNMP.port,
|
91
84
|
version: config[ 'version' ] || Arborist::Monitor::SNMP.version,
|
92
85
|
community: config[ 'community' ] || Arborist::Monitor::SNMP.community,
|
@@ -94,22 +87,17 @@ module Arborist::Monitor::SNMP
|
|
94
87
|
retries: config[ 'retries' ] || Arborist::Monitor::SNMP.retries
|
95
88
|
}
|
96
89
|
|
97
|
-
snmp = Net::SNMP::Session.open( opts )
|
98
90
|
begin
|
99
|
-
|
100
|
-
|
91
|
+
NETSNMP::Client.new( opts ) do |snmp|
|
92
|
+
Thread.current[ :system ] = snmp.get( oid: IDENTIFICATION_OID )
|
93
|
+
yield( host, snmp )
|
94
|
+
end
|
101
95
|
|
102
|
-
rescue Net::SNMP::TimeoutError, Net::SNMP::Error => err
|
103
|
-
self.log.error "%s: %s %s" % [ host, err.message, snmp.error_message ]
|
104
|
-
self.results[ host ] = {
|
105
|
-
error: "%s" % [ snmp.error_message ]
|
106
|
-
}
|
107
96
|
rescue => err
|
97
|
+
self.log.error "%s: %s\n%s" % [ host, err.message, err.backtrace.join("\n ") ]
|
108
98
|
self.results[ host ] = {
|
109
|
-
error: "
|
99
|
+
error: "Exception (%s: %s)" % [ err.class.name, err.message ]
|
110
100
|
}
|
111
|
-
ensure
|
112
|
-
snmp.close
|
113
101
|
end
|
114
102
|
end
|
115
103
|
|
@@ -135,6 +123,12 @@ module Arborist::Monitor::SNMP
|
|
135
123
|
@results = {}
|
136
124
|
end
|
137
125
|
|
126
|
+
|
127
|
+
### Return the current SNMP connection system string.
|
128
|
+
def system
|
129
|
+
return Thread.current[ :system ]
|
130
|
+
end
|
131
|
+
|
138
132
|
end # Arborist::Monitor::SNMP
|
139
133
|
|
140
134
|
require 'arborist/monitor/snmp/cpu'
|
@@ -66,18 +66,13 @@ class Arborist::Monitor::SNMP::CPU
|
|
66
66
|
protected
|
67
67
|
#########
|
68
68
|
|
69
|
-
### Return system CPU data.
|
70
|
-
###
|
71
|
-
def cpu( snmp )
|
72
|
-
return snmp.walk( OIDS[:cpu] )
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
69
|
### Find load data, add additional niceties for reporting.
|
77
70
|
###
|
78
71
|
def format_load( snmp )
|
79
72
|
info = { cpu: {}, load: {} }
|
80
|
-
cpus =
|
73
|
+
cpus = snmp.walk( oid: OIDS[:cpu] ).each_with_object( [] ) do |(_, value), acc|
|
74
|
+
acc << value
|
75
|
+
end
|
81
76
|
|
82
77
|
info[ :cpu ][ :count ] = cpus.size
|
83
78
|
|
@@ -91,20 +86,21 @@ class Arborist::Monitor::SNMP::CPU
|
|
91
86
|
# alert after X events" pragmas.
|
92
87
|
#
|
93
88
|
if self.system =~ /windows\s+/i
|
94
|
-
info[ :cpu ][ :usage ] = cpus.
|
89
|
+
info[ :cpu ][ :usage ] = cpus.inject( :+ ).to_f / cpus.size
|
95
90
|
info[ :message ] = "System is %0.1f%% in use." % [ info[ :cpu ][ :usage ] ]
|
96
91
|
|
92
|
+
|
97
93
|
# UCDavis stuff is better for alerting only after there has been
|
98
94
|
# an extended load event. Use the 5 minute average to avoid
|
99
95
|
# state changes on transient spikes.
|
100
96
|
#
|
101
97
|
else
|
102
|
-
snmp.walk( OIDS[:load] ).each_with_index do |(_, value), idx|
|
98
|
+
snmp.walk( oid: OIDS[:load] ).each_with_index do |(_, value), idx|
|
103
99
|
next unless LOADKEYS[ idx + 1 ]
|
104
100
|
info[ :load ][ LOADKEYS[idx + 1] ] = value.to_f
|
105
101
|
end
|
106
102
|
|
107
|
-
percentage = (( ( info[:load][ :load5 ] / cpus.size
|
103
|
+
percentage = (( ( info[:load][ :load5 ] / cpus.size) - 1 ) * 100 ).round( 1 )
|
108
104
|
|
109
105
|
if percentage < 0
|
110
106
|
info[ :message ] = "System is %0.1f%% idle." % [ percentage.abs ]
|
@@ -60,7 +60,7 @@ class Arborist::Monitor::SNMP::Disk
|
|
60
60
|
# Paths to exclude from checks
|
61
61
|
#
|
62
62
|
setting :exclude,
|
63
|
-
default: [ '^/dev(/.+)?$', '^/net(/.+)?$', '
|
63
|
+
default: [ '^/dev(/.+)?$', '/dev$', '^/net(/.+)?$', '/proc$', '^/run$', '^/sys/', '/sys$' ] do |val|
|
64
64
|
mounts = Array( val ).map{|m| Regexp.new(m) }
|
65
65
|
Regexp.union( mounts )
|
66
66
|
end
|
@@ -106,6 +106,7 @@ class Arborist::Monitor::SNMP::Disk
|
|
106
106
|
excludes = self.format_mounts( config, 'exclude' ) || self.class.exclude
|
107
107
|
|
108
108
|
mounts.reject! do |path, percentage|
|
109
|
+
path = path.to_s
|
109
110
|
excludes.match( path ) || ( includes && ! includes.match( path ) )
|
110
111
|
end
|
111
112
|
|
@@ -113,12 +114,10 @@ class Arborist::Monitor::SNMP::Disk
|
|
113
114
|
warnings = []
|
114
115
|
mounts.each_pair do |path, percentage|
|
115
116
|
|
116
|
-
warn =
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
warn_at
|
121
|
-
end
|
117
|
+
warn = if warn_at.is_a?( Hash )
|
118
|
+
warn_at[ path ] || WARN_AT
|
119
|
+
else
|
120
|
+
warn_at
|
122
121
|
end
|
123
122
|
|
124
123
|
self.log.debug "%s:%s -> at %d, warn at %d" % [ host, path, percentage, warn ]
|
@@ -151,18 +150,32 @@ class Arborist::Monitor::SNMP::Disk
|
|
151
150
|
### Fetch information for Windows systems.
|
152
151
|
###
|
153
152
|
def windows_disks( snmp )
|
154
|
-
|
153
|
+
oids = [
|
155
154
|
STORAGE_WINDOWS[:path],
|
156
155
|
STORAGE_WINDOWS[:type],
|
157
156
|
STORAGE_WINDOWS[:total],
|
158
157
|
STORAGE_WINDOWS[:used]
|
159
|
-
]
|
158
|
+
]
|
159
|
+
|
160
|
+
paths = snmp.walk( oid: oids[0] ).each_with_object( [] ) do |(_, value), acc|
|
161
|
+
acc << value
|
162
|
+
end
|
163
|
+
types = snmp.walk( oid: oids[1] ).each_with_object( [] ) do |(_, value), acc|
|
164
|
+
acc << WINDOWS_DEVICES.include?( value )
|
165
|
+
end
|
166
|
+
totals = snmp.walk( oid: oids[2] ).each_with_object( [] ) do |(_, value), acc|
|
167
|
+
acc << value
|
168
|
+
end
|
169
|
+
used = snmp.walk( oid: oids[3] ).each_with_object( [] ) do |(_, value), acc|
|
170
|
+
acc << value
|
171
|
+
end
|
160
172
|
|
161
173
|
disks = {}
|
162
|
-
|
163
|
-
next
|
164
|
-
next
|
165
|
-
disks[
|
174
|
+
paths.each_with_index do |path, idx|
|
175
|
+
next if totals[ idx ].zero?
|
176
|
+
next unless types[ idx ]
|
177
|
+
disks[ path ] ||= {}
|
178
|
+
disks[ path ] = (( used[idx].to_f / totals[idx] ) * 100).round( 1 )
|
166
179
|
end
|
167
180
|
|
168
181
|
return disks
|
@@ -172,11 +185,16 @@ class Arborist::Monitor::SNMP::Disk
|
|
172
185
|
### Fetch information for Unix/MacOS systems.
|
173
186
|
###
|
174
187
|
def unix_disks( snmp )
|
175
|
-
|
176
|
-
|
177
|
-
|
188
|
+
oids = [ STORAGE_NET_SNMP[:path], STORAGE_NET_SNMP[:percent] ]
|
189
|
+
paths = snmp.walk( oid: oids.first ).each_with_object( [] ) do |(_, value), acc|
|
190
|
+
acc << value
|
191
|
+
end
|
192
|
+
capacities = snmp.walk( oid: oids.last ).each_with_object( [] ) do |(_, value), acc|
|
193
|
+
acc << value
|
194
|
+
end
|
178
195
|
|
179
|
-
|
196
|
+
pairs = paths.zip( capacities )
|
197
|
+
return Hash[ *pairs.flatten ]
|
180
198
|
end
|
181
199
|
|
182
200
|
end # class Arborist::Monitor::SNMP::Disk
|
@@ -131,7 +131,7 @@ class Arborist::Monitor::SNMP::Memory
|
|
131
131
|
info = { memory: {}, swap: {} }
|
132
132
|
mem_idx, swap_idx = nil
|
133
133
|
|
134
|
-
snmp.walk( MEMORY[:windows][:label] ).each_with_index do |(_, val), i|
|
134
|
+
snmp.walk( oid: MEMORY[:windows][:label] ).each_with_index do |(_, val), i|
|
135
135
|
mem_idx = i + 1 if val =~ /physical memory/i
|
136
136
|
swap_idx = i + 1 if val =~ /virtual memory/i
|
137
137
|
end
|
@@ -148,8 +148,8 @@ class Arborist::Monitor::SNMP::Memory
|
|
148
148
|
###
|
149
149
|
def calc_memory( snmp, oids )
|
150
150
|
info = { usage: 0, available: 0 }
|
151
|
-
avail = snmp.get( oids[:avail] ).
|
152
|
-
total = snmp.get( oids[:total] ).
|
151
|
+
avail = snmp.get( oid: oids[:avail] ).to_f
|
152
|
+
total = snmp.get( oid: oids[:total] ).to_f
|
153
153
|
used = total - avail
|
154
154
|
|
155
155
|
return info if avail.zero?
|
@@ -166,9 +166,9 @@ class Arborist::Monitor::SNMP::Memory
|
|
166
166
|
info = { usage: 0, available: 0 }
|
167
167
|
return info unless idx
|
168
168
|
|
169
|
-
units = snmp.get( MEMORY[:windows][:units] + ".#{idx}" )
|
170
|
-
total = snmp.get( MEMORY[:windows][:total] + ".#{idx}" ).
|
171
|
-
used = snmp.get( MEMORY[:windows][:used] + ".#{idx}" ).
|
169
|
+
units = snmp.get( oid: MEMORY[:windows][:units] + ".#{idx}" )
|
170
|
+
total = snmp.get( oid: MEMORY[:windows][:total] + ".#{idx}" ).to_f * units
|
171
|
+
used = snmp.get( oid: MEMORY[:windows][:used] + ".#{idx}" ).to_f * units
|
172
172
|
|
173
173
|
info[ :usage ] = (( used / total ) * 100 ).round( 2 )
|
174
174
|
info[ :available ] = (( total - used ) / 1024 / 1024 ).round( 2 )
|
@@ -80,7 +80,7 @@ class Arborist::Monitor::SNMP::Process
|
|
80
80
|
|
81
81
|
# Check against what is running.
|
82
82
|
#
|
83
|
-
Array( config['
|
83
|
+
Array( config['check'] || self.class.check ).each do |process|
|
84
84
|
process_r = Regexp.new( process )
|
85
85
|
found = procs.find{|p| p.match(process_r) }
|
86
86
|
errors << "'%s' is not running" % [ process ] unless found
|
@@ -95,14 +95,24 @@ class Arborist::Monitor::SNMP::Process
|
|
95
95
|
###
|
96
96
|
def get_windows( snmp )
|
97
97
|
oids = [ PROCESS[:windows][:path], PROCESS[:windows][:list], PROCESS[:windows][:args] ]
|
98
|
-
return snmp.walk( oids ).each_slice( 3 ). each_with_object( [] ) do |vals, acc|
|
99
|
-
path, process, args = vals[0][1], vals[1][1], vals[2][1]
|
100
|
-
next if path.empty?
|
101
98
|
|
102
|
-
|
103
|
-
|
104
|
-
|
99
|
+
paths = snmp.walk( oid: oids[0] ).each_with_object( [] ) do |(_, value), acc|
|
100
|
+
acc << value
|
101
|
+
end
|
102
|
+
procs = snmp.walk( oid: oids[1] ).each_with_object( [] ) do |(_, value), acc|
|
103
|
+
acc << value
|
104
|
+
end
|
105
|
+
args = snmp.walk( oid: oids[2] ).each_with_object( [] ) do |(_, value), acc|
|
106
|
+
acc << value
|
105
107
|
end
|
108
|
+
|
109
|
+
return paths.zip( procs, args ).collect do |(path, process, arg)|
|
110
|
+
next unless path && process
|
111
|
+
next if path.empty?
|
112
|
+
path << process unless process.empty?
|
113
|
+
path << " %s" % [ arg.to_s ] if arg && ! arg.empty?
|
114
|
+
path
|
115
|
+
end.compact
|
106
116
|
end
|
107
117
|
|
108
118
|
|
@@ -110,13 +120,19 @@ class Arborist::Monitor::SNMP::Process
|
|
110
120
|
###
|
111
121
|
def get_procs( snmp )
|
112
122
|
oids = [ PROCESS[:netsnmp][:list], PROCESS[:netsnmp][:args] ]
|
113
|
-
return snmp.walk( oids ).each_slice( 2 ).each_with_object( [] ) do |vals, acc|
|
114
|
-
process, args = vals[0][1], vals[1][1]
|
115
|
-
next if process.empty?
|
116
123
|
|
117
|
-
|
118
|
-
acc <<
|
124
|
+
procs = snmp.walk( oid: oids.first ).each_with_object( [] ) do |(_, value), acc|
|
125
|
+
acc << value
|
126
|
+
end
|
127
|
+
args = snmp.walk( oid: oids.last ).each_with_object( [] ) do |(_, value), acc|
|
128
|
+
acc << value
|
119
129
|
end
|
130
|
+
|
131
|
+
return procs.zip( args ).collect do |(process, arg)|
|
132
|
+
next if process.empty?
|
133
|
+
process << " %s" % [ arg.to_s ] unless arg.empty?
|
134
|
+
process
|
135
|
+
end.compact
|
120
136
|
end
|
121
137
|
|
122
138
|
end # class Arborist::Monitor::SNMP::Process
|
data/lib/arborist/snmp.rb
CHANGED
@@ -14,10 +14,10 @@ module Arborist::SNMP
|
|
14
14
|
|
15
15
|
|
16
16
|
# Package version
|
17
|
-
VERSION = '0.
|
17
|
+
VERSION = '0.5.0'
|
18
18
|
|
19
19
|
# Version control revision
|
20
|
-
REVISION = %q$Revision:
|
20
|
+
REVISION = %q$Revision: e4f0fd44734d $
|
21
21
|
|
22
22
|
|
23
23
|
### Return the name of the library with the version, and optionally the build ID if
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arborist-snmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mahlon E. Smith <mahlon@martini.nu>
|
@@ -31,7 +31,7 @@ cert_chain:
|
|
31
31
|
n0YyneERGuHPSRZFgo72tGOqLpAlWnhPxRNqnayZmsg3hPPI87B6MTUI2UQ7VUdh
|
32
32
|
UrSf3b+cPoC8PNfjp8zsdw==
|
33
33
|
-----END CERTIFICATE-----
|
34
|
-
date: 2018-
|
34
|
+
date: 2018-06-13 00:00:00.000000000 Z
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: arborist
|
@@ -48,19 +48,33 @@ dependencies:
|
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '0.1'
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
|
-
name:
|
51
|
+
name: netsnmp
|
52
52
|
requirement: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: '0.
|
56
|
+
version: '0.1'
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0.1'
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
name: xorcist
|
66
|
+
requirement: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '1.1'
|
57
71
|
type: :runtime
|
58
72
|
prerelease: false
|
59
73
|
version_requirements: !ruby/object:Gem::Requirement
|
60
74
|
requirements:
|
61
75
|
- - "~>"
|
62
76
|
- !ruby/object:Gem::Version
|
63
|
-
version: '
|
77
|
+
version: '1.1'
|
64
78
|
description: "\tThis library adds common SNMP resource support to Arborist monitors.\n"
|
65
79
|
email: mahlon@martini.nu
|
66
80
|
executables: []
|
@@ -93,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
107
|
version: '0'
|
94
108
|
requirements: []
|
95
109
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.5.1
|
110
|
+
rubygems_version: 2.5.2.1
|
97
111
|
signing_key:
|
98
112
|
specification_version: 4
|
99
113
|
summary: SNMP support for Arborist monitors
|