arborist-snmp 0.1.0.pre20161005111600
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +4 -0
- data/lib/arborist/monitor/snmp.rb +402 -0
- data.tar.gz.sig +0 -0
- metadata +97 -0
- metadata.gz.sig +2 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 639227f1252bedce794f5bfabada161a9ff3d8a2
|
4
|
+
data.tar.gz: 713cc9b8bf1fc6fc467b688d9d38656be3e193c9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94b2a8a87fe45817464ddff645ab1058a6ab3577afd893cfc0b2837737ce3240567cf52c6982379a2886ba9590cf0674106ab601cf5ad0e82cc869e005754ffb
|
7
|
+
data.tar.gz: b34cc56ac99c63333a020b5ecf201daf74d310dbe2447fec3568713e128fec3c0cdaaa36a15d7833b4cc2975f5bb14943b9127ef3b62ca3c884106fc1a203212
|
checksums.yaml.gz.sig
ADDED
@@ -0,0 +1,402 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set noet nosta sw=4 ts=4 :
|
3
|
+
#encoding: utf-8
|
4
|
+
#
|
5
|
+
# SNMP checks for Arborist. Requires an SNMP agent to be installed
|
6
|
+
# on target machine, and the various "pieces" enabled. For your platform.
|
7
|
+
#
|
8
|
+
# For example, for disk monitoring with Net-SNMP, you'll want to set
|
9
|
+
# 'includeAllDisks' in the snmpd.conf. bsnmpd on FreeBSD benefits from
|
10
|
+
# the 'bsnmp-ucd' package. Etc.
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'loggability'
|
14
|
+
require 'arborist/monitor' unless defined?( Arborist::Monitor )
|
15
|
+
require 'snmp'
|
16
|
+
|
17
|
+
using Arborist::TimeRefinements
|
18
|
+
|
19
|
+
# SNMP specific monitors and monitor logic.
|
20
|
+
#
|
21
|
+
class Arborist::Monitor::SNMP
|
22
|
+
extend Loggability
|
23
|
+
log_to :arborist
|
24
|
+
|
25
|
+
# The version of this library.
|
26
|
+
VERSION = '0.1.0'
|
27
|
+
|
28
|
+
# "Modes" that this monitor understands.
|
29
|
+
VALID_MODES = %i[ disk load memory swap process ]
|
30
|
+
|
31
|
+
# The OID that returns the system environment.
|
32
|
+
IDENTIFICATION_OID = '1.3.6.1.2.1.1.1.0'
|
33
|
+
|
34
|
+
# For net-snmp systems, ignore mount types that match
|
35
|
+
# this regular expression. This includes null/union mounts
|
36
|
+
# and NFS, currently.
|
37
|
+
STORAGE_IGNORE = %r{25.3.9.(?:2|14)$}
|
38
|
+
|
39
|
+
# The OID that matches a local windows hard disk. Anything else
|
40
|
+
# is a remote (SMB) mount.
|
41
|
+
WINDOWS_DEVICE = '1.3.6.1.2.1.25.2.1.4'
|
42
|
+
|
43
|
+
# OIDS required to pull disk information from net-snmp.
|
44
|
+
#
|
45
|
+
STORAGE_NET_SNMP = [
|
46
|
+
'1.3.6.1.4.1.2021.9.1.2', # paths
|
47
|
+
'1.3.6.1.2.1.25.3.8.1.4', # types
|
48
|
+
'1.3.6.1.4.1.2021.9.1.9' # percents
|
49
|
+
]
|
50
|
+
|
51
|
+
# OIDS required to pull disk information from Windows.
|
52
|
+
#
|
53
|
+
STORAGE_WINDOWS = [
|
54
|
+
'1.3.6.1.2.1.25.2.3.1.2', # types
|
55
|
+
'1.3.6.1.2.1.25.2.3.1.3', # paths
|
56
|
+
'1.3.6.1.2.1.25.2.3.1.5', # totalsize
|
57
|
+
'1.3.6.1.2.1.25.2.3.1.6' # usedsize
|
58
|
+
]
|
59
|
+
|
60
|
+
# OIDS for discovering memory usage.
|
61
|
+
#
|
62
|
+
MEMORY = {
|
63
|
+
swap_total: '1.3.6.1.4.1.2021.4.3.0',
|
64
|
+
swap_avail: '1.3.6.1.4.1.2021.4.4.0',
|
65
|
+
mem_avail: '1.3.6.1.4.1.2021.4.6.0'
|
66
|
+
}
|
67
|
+
|
68
|
+
# OIDS for discovering system load.
|
69
|
+
#
|
70
|
+
LOAD = {
|
71
|
+
five_min: '1.3.6.1.4.1.2021.10.1.3.2'
|
72
|
+
}
|
73
|
+
|
74
|
+
# OIDS for discovering running processes.
|
75
|
+
#
|
76
|
+
PROCESS = {
|
77
|
+
list: '1.3.6.1.2.1.25.4.2.1.4',
|
78
|
+
args: '1.3.6.1.2.1.25.4.2.1.5'
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
# Defaults for instances of this monitor
|
83
|
+
#
|
84
|
+
DEFAULT_OPTIONS = {
|
85
|
+
timeout: 2,
|
86
|
+
retries: 1,
|
87
|
+
community: 'public',
|
88
|
+
port: 161,
|
89
|
+
storage_error_at: 95, # in percent full
|
90
|
+
load_error_at: 7,
|
91
|
+
swap_error_at: 25, # in percent remaining
|
92
|
+
mem_error_at: 51200, # in kilobytes
|
93
|
+
processes: [] # list of procs to match
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
### This monitor is complex enough to require creating an instance from the caller.
|
98
|
+
### Provide a friendlier error message the class was provided to exec() directly.
|
99
|
+
###
|
100
|
+
def self::run( nodes )
|
101
|
+
self.log.error "Please use %s via an instance." % [ self.name ]
|
102
|
+
return {}
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
### Create a new instance of this monitor.
|
107
|
+
###
|
108
|
+
def initialize( options=DEFAULT_OPTIONS )
|
109
|
+
options = DEFAULT_OPTIONS.merge( options || {} )
|
110
|
+
|
111
|
+
options.each do |name, value|
|
112
|
+
self.public_send( "#{name}=", value )
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
# The mode (section) that this SMMP instance should check.
|
118
|
+
# Must be a +VALID_MODES+ mode.
|
119
|
+
attr_reader :mode
|
120
|
+
|
121
|
+
# Mapping of node addresses back to the node identifier.
|
122
|
+
attr_reader :identifiers
|
123
|
+
|
124
|
+
# The results from the SNMP daemons, keyed by address.
|
125
|
+
attr_reader :results
|
126
|
+
|
127
|
+
# A timeout in seconds if the SNMP server isn't responding.
|
128
|
+
attr_accessor :timeout
|
129
|
+
|
130
|
+
# Retry with the timeout this many times. Defaults to 1.
|
131
|
+
attr_accessor :retries
|
132
|
+
|
133
|
+
# The SNMP UDP port, if running on non default.
|
134
|
+
attr_accessor :port
|
135
|
+
|
136
|
+
# The community string to connect with.
|
137
|
+
attr_accessor :community
|
138
|
+
|
139
|
+
# Set an error if mount points are above this percentage.
|
140
|
+
attr_accessor :storage_error_at
|
141
|
+
|
142
|
+
# Set an error if the 5 minute load average exceeds this.
|
143
|
+
attr_accessor :load_error_at
|
144
|
+
|
145
|
+
# Set an error if used swap exceeds this percentage.
|
146
|
+
attr_accessor :swap_error_at
|
147
|
+
|
148
|
+
# Set an error if memory used is below this many kilobytes.
|
149
|
+
attr_accessor :mem_error_at
|
150
|
+
|
151
|
+
# Set an error if processes in this array aren't running.
|
152
|
+
attr_accessor :processes
|
153
|
+
|
154
|
+
|
155
|
+
### Set the SNMP mode, after validation.
|
156
|
+
###
|
157
|
+
def mode=( mode )
|
158
|
+
unless VALID_MODES.include?( mode.to_sym )
|
159
|
+
self.log.error "Unknown SNMP mode: %s" % [ mode ]
|
160
|
+
return nil
|
161
|
+
end
|
162
|
+
|
163
|
+
@mode = mode.to_sym
|
164
|
+
@results = {}
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
### Perform the monitoring checks.
|
169
|
+
###
|
170
|
+
def run( nodes )
|
171
|
+
self.log.debug "Got nodes to SNMP check: %p" % [ nodes ]
|
172
|
+
|
173
|
+
# Sanity check.
|
174
|
+
#
|
175
|
+
unless self.mode
|
176
|
+
self.log.error "You must set the 'mode' for the SNMP monitor. (%s)" % [ VALID_MODES.join( ', ' ) ]
|
177
|
+
return {}
|
178
|
+
end
|
179
|
+
|
180
|
+
# Create mapping of addresses back to node identifiers.
|
181
|
+
#
|
182
|
+
@identifiers = nodes.each_with_object({}) do |(identifier, props), hash|
|
183
|
+
next unless props.key?( 'addresses' )
|
184
|
+
address = props[ 'addresses' ].first
|
185
|
+
hash[ address ] = identifier
|
186
|
+
end
|
187
|
+
|
188
|
+
# Perform the work!
|
189
|
+
#
|
190
|
+
threads = []
|
191
|
+
self.identifiers.keys.each do |host|
|
192
|
+
thr = Thread.new do
|
193
|
+
Thread.current.abort_on_exception = true
|
194
|
+
opts = {
|
195
|
+
host: host,
|
196
|
+
port: self.port,
|
197
|
+
community: self.community,
|
198
|
+
timeout: self.timeout,
|
199
|
+
retries: self.retries
|
200
|
+
}
|
201
|
+
|
202
|
+
begin
|
203
|
+
SNMP::Manager.open( opts ) do |snmp|
|
204
|
+
case self.mode
|
205
|
+
when :disk
|
206
|
+
self.gather_disks( snmp, host )
|
207
|
+
when :load
|
208
|
+
self.gather_load( snmp, host )
|
209
|
+
when :memory
|
210
|
+
self.gather_free_memory( snmp, host )
|
211
|
+
when :swap
|
212
|
+
self.gather_swap( snmp, host )
|
213
|
+
when :process
|
214
|
+
self.gather_processlist( snmp, host )
|
215
|
+
end
|
216
|
+
end
|
217
|
+
rescue SNMP::RequestTimeout
|
218
|
+
self.results[ host ] = {
|
219
|
+
error: "Host is not responding to SNMP requests."
|
220
|
+
}
|
221
|
+
rescue StandardError => err
|
222
|
+
self.results[ host ] = {
|
223
|
+
error: "Network is not accessible. (%s: %s)" % [ err.class.name, err.message ]
|
224
|
+
}
|
225
|
+
end
|
226
|
+
end
|
227
|
+
threads << thr
|
228
|
+
end
|
229
|
+
|
230
|
+
# Wait for thread completion
|
231
|
+
threads.map( &:join )
|
232
|
+
|
233
|
+
# Map everything back to identifier -> attribute(s), and send to the manager.
|
234
|
+
#
|
235
|
+
reply = self.results.each_with_object({}) do |(address, results), hash|
|
236
|
+
identifier = self.identifiers[ address ] or next
|
237
|
+
hash[ identifier ] = results
|
238
|
+
end
|
239
|
+
self.log.debug "Sending to manager: %p" % [ reply ]
|
240
|
+
return reply
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
#########
|
245
|
+
protected
|
246
|
+
#########
|
247
|
+
|
248
|
+
### Collect the load information for +host+ from an existing
|
249
|
+
### (and open) +snmp+ connection.
|
250
|
+
###
|
251
|
+
def gather_load( snmp, host )
|
252
|
+
self.log.debug "Getting system load for: %s" % [ host ]
|
253
|
+
load5 = snmp.get( SNMP::ObjectId.new( LOAD[:five_min] ) ).varbind_list.first.value.to_f
|
254
|
+
self.log.debug " Load on %s: %0.2f" % [ host, load5 ]
|
255
|
+
|
256
|
+
if load5 >= self.load_error_at
|
257
|
+
self.results[ host ] = {
|
258
|
+
error: "Load has exceeded %0.2f over a 5 minute average" % [ self.load_error_at ],
|
259
|
+
load5: load5
|
260
|
+
}
|
261
|
+
else
|
262
|
+
self.results[ host ] = { load5: load5 }
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
### Collect available memory information for +host+ from an existing
|
268
|
+
### (and open) +snmp+ connection.
|
269
|
+
###
|
270
|
+
def gather_free_memory( snmp, host )
|
271
|
+
self.log.debug "Getting available memory for: %s" % [ host ]
|
272
|
+
mem_avail = snmp.get( SNMP::ObjectId.new( MEMORY[:mem_avail] ) ).varbind_list.first.value.to_f
|
273
|
+
self.log.debug " Available memory on %s: %0.2f" % [ host, mem_avail ]
|
274
|
+
|
275
|
+
if mem_avail <= self.mem_error_at
|
276
|
+
self.results[ host ] = {
|
277
|
+
error: "Available memory is under %0.1fMB" % [ self.mem_error_at.to_f / 1024 ],
|
278
|
+
available_memory: mem_avail
|
279
|
+
}
|
280
|
+
else
|
281
|
+
self.results[ host ] = { available_memory: mem_avail }
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
### Collect used swap information for +host+ from an existing (and
|
287
|
+
### open) +snmp+ connection.
|
288
|
+
###
|
289
|
+
def gather_swap( snmp, host )
|
290
|
+
self.log.debug "Getting used swap for: %s" % [ host ]
|
291
|
+
|
292
|
+
swap_total = snmp.get( SNMP::ObjectId.new(MEMORY[:swap_total]) ).varbind_list.first.value.to_f
|
293
|
+
swap_avail = snmp.get( SNMP::ObjectId.new(MEMORY[:swap_avail]) ).varbind_list.first.value.to_f
|
294
|
+
swap_used = ( "%0.2f" % ((swap_avail / swap_total.to_f * 100 ) - 100).abs ).to_f
|
295
|
+
self.log.debug " Swap in use on %s: %0.2f" % [ host, swap_used ]
|
296
|
+
|
297
|
+
if swap_used >= self.swap_error_at
|
298
|
+
self.results[ host ] = {
|
299
|
+
error: "%0.2f%% swap in use" % [ swap_used ],
|
300
|
+
swap_used: swap_used
|
301
|
+
}
|
302
|
+
else
|
303
|
+
self.results[ host ] = { swap_used: swap_used }
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
|
308
|
+
### Collect mount point usage for +host+ from an existing (and open)
|
309
|
+
#### +snmp+ connection.
|
310
|
+
###
|
311
|
+
def gather_disks( snmp, host )
|
312
|
+
self.log.debug "Getting disk information for %s" % [ host ]
|
313
|
+
errors = []
|
314
|
+
results = {}
|
315
|
+
mounts = self.get_disk_percentages( snmp )
|
316
|
+
|
317
|
+
mounts.each_pair do |path, percentage|
|
318
|
+
if percentage >= self.storage_error_at
|
319
|
+
errors << "Mount %s at %d%% capacity" % [ path, percentage ]
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
results[ :mounts ] = mounts
|
324
|
+
results[ :error ] = errors.join( ', ' ) unless errors.empty?
|
325
|
+
|
326
|
+
self.results[ host ] = results
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
### Collect running processes on +host+ from an existing (and open)
|
331
|
+
#### +snmp+ connection.
|
332
|
+
###
|
333
|
+
def gather_processlist( snmp, host )
|
334
|
+
self.log.debug "Getting running process list for %s" % [ host ]
|
335
|
+
procs = []
|
336
|
+
|
337
|
+
snmp.walk([ PROCESS[:list], PROCESS[:args] ]) do |list|
|
338
|
+
process = list[0].value.to_s
|
339
|
+
args = list[1].value.to_s
|
340
|
+
procs << "%s %s " % [ process, args ]
|
341
|
+
end
|
342
|
+
|
343
|
+
# Check against the running stuff, setting an error if
|
344
|
+
# one isn't found.
|
345
|
+
#
|
346
|
+
errors = []
|
347
|
+
Array( self.processes ).each do |process|
|
348
|
+
process_r = Regexp.new( process )
|
349
|
+
found = procs.find{|p| p.match(process_r) }
|
350
|
+
errors << "Process '%s' is not running" % [ process, host ] unless found
|
351
|
+
end
|
352
|
+
|
353
|
+
self.log.debug " %d running processes" % [ procs.length ]
|
354
|
+
if errors.empty?
|
355
|
+
self.results[ host ] = {}
|
356
|
+
else
|
357
|
+
self.results[ host ] = { error: errors.join( ', ' ) }
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
|
362
|
+
### Given a SNMP object, return a hash of:
|
363
|
+
###
|
364
|
+
### device path => percentage full
|
365
|
+
###
|
366
|
+
def get_disk_percentages( snmp )
|
367
|
+
|
368
|
+
# Does this look like a windows system, or a net-snmp based one?
|
369
|
+
system_type = snmp.get( SNMP::ObjectId.new( IDENTIFICATION_OID ) ).varbind_list.first.value
|
370
|
+
disks = {}
|
371
|
+
|
372
|
+
# Windows has it's own MIBs.
|
373
|
+
#
|
374
|
+
if system_type =~ /windows/i
|
375
|
+
snmp.walk( STORAGE_WINDOWS ) do |list|
|
376
|
+
next unless list[0].value.to_s == WINDOWS_DEVICE
|
377
|
+
disks[ list[1].value.to_s ] = ( list[3].value.to_f / list[2].value.to_f ) * 100
|
378
|
+
end
|
379
|
+
return disks
|
380
|
+
end
|
381
|
+
|
382
|
+
# Everything else.
|
383
|
+
#
|
384
|
+
snmp.walk( STORAGE_NET_SNMP ) do |list|
|
385
|
+
mount = list[0].value.to_s
|
386
|
+
next if mount == 'noSuchInstance'
|
387
|
+
|
388
|
+
next if list[2].value.to_s == 'noSuchInstance'
|
389
|
+
used = list[2].value.to_i
|
390
|
+
|
391
|
+
typeoid = list[1].value.join('.').to_s
|
392
|
+
next if typeoid =~ STORAGE_IGNORE
|
393
|
+
next if mount =~ /\/(?:dev|proc)$/
|
394
|
+
|
395
|
+
self.log.debug " %s -> %s -> %s" % [ mount, typeoid, used ]
|
396
|
+
disks[ mount ] = used
|
397
|
+
end
|
398
|
+
|
399
|
+
return disks
|
400
|
+
end
|
401
|
+
end # class Arborist::Monitor::SNMP
|
402
|
+
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: arborist-snmp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre20161005111600
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mahlon E. Smith
|
8
|
+
- Michael Granger
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
- |
|
13
|
+
-----BEGIN CERTIFICATE-----
|
14
|
+
MIIDbDCCAlSgAwIBAgIBATANBgkqhkiG9w0BAQUFADA+MQ8wDQYDVQQDDAZtYWhs
|
15
|
+
b24xFzAVBgoJkiaJk/IsZAEZFgdtYXJ0aW5pMRIwEAYKCZImiZPyLGQBGRYCbnUw
|
16
|
+
HhcNMTYwNjI5MjMzMzI2WhcNMTcwNjI5MjMzMzI2WjA+MQ8wDQYDVQQDDAZtYWhs
|
17
|
+
b24xFzAVBgoJkiaJk/IsZAEZFgdtYXJ0aW5pMRIwEAYKCZImiZPyLGQBGRYCbnUw
|
18
|
+
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpXGN0YbMVpYv4EoiCxpQw
|
19
|
+
sxKdyhlkvpvENUkpEhbpnEuMKXgUfRHO4T/vBZf0h8eYgwnrHCRhAeIqesFKfoj9
|
20
|
+
mpEJk5JUuADOAz18aT+v24UqAtJdiwBJLuqhslSNB6CFXZv3OOMny9bjoJegz0hI
|
21
|
+
Fht9ppCuNmxJNd+L3zAX8lD01RUWNRC+8L5QLCjViJtjFDDCFfh9NCirs+XnTCzo
|
22
|
+
AJgFbsZIzFJtSiXUtFgscKr4Ik8ruhRbPbYbmx9rf6W74aTMPxggq/d3gj0Eh32y
|
23
|
+
WsXsQ5giVnmkbsRkBNu3QyZ8Xr5+7mvy5AWyqXKOrcW7lnYaob6Z9x/MGXGNeD6j
|
24
|
+
AgMBAAGjdTBzMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRY8ea6
|
25
|
+
+6kAaW7ukKph2/4MTAD8/TAcBgNVHREEFTATgRFtYWhsb25AbWFydGluaS5udTAc
|
26
|
+
BgNVHRIEFTATgRFtYWhsb25AbWFydGluaS5udTANBgkqhkiG9w0BAQUFAAOCAQEA
|
27
|
+
EU39m2ZKYqAAu71bwjWl5zEAk0aE4ojMLIMWpWE6IwCr9FZVpC1B+LyEboWFljId
|
28
|
+
R0udISkfM+kQ3FRzmnwwQLaYJyhDPEWbQ1O6P6wHCaUQ23A1P++dZf8PWuZkS6Dn
|
29
|
+
C1q7Zq4EAZEBLUSK69iPP4jCLjIp3YBQ88D1/egA+hkrR/19m236PvhhaM9FTgQv
|
30
|
+
LtL61M3ZtlTanoXiNbXRXwRnODzvjFpQRiiBiazCDBYj8oYDsNj+qNw/iZlZlzw5
|
31
|
+
F6uYXeS4YCZP453ZcpgZkXo3F5RheTrkdf04DMwUpQPMKog9QmRSTlCxzH69kivQ
|
32
|
+
IfRp+58YwWwtAIQPZoY6Rg==
|
33
|
+
-----END CERTIFICATE-----
|
34
|
+
date: 2016-10-05 00:00:00.000000000 Z
|
35
|
+
dependencies:
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: snmp
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.2'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.2'
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: arborist
|
52
|
+
requirement: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
description: "\tThis library adds common SNMP support to Arborist monitors.\n"
|
65
|
+
email:
|
66
|
+
- mahlon@martini.nu
|
67
|
+
- ged@faeriemud.org
|
68
|
+
executables: []
|
69
|
+
extensions: []
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- lib/arborist/monitor/snmp.rb
|
73
|
+
homepage: http://bitbucket.org/mahlon/Arborist-SNMP
|
74
|
+
licenses:
|
75
|
+
- BSD-3-Clause
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '2'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.3.1
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 2.5.1
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Common SNMP support for Arborist
|
97
|
+
test_files: []
|
metadata.gz.sig
ADDED