author | Mahlon E. Smith <mahlon@martini.nu> |
Sat, 01 Aug 2020 14:17:50 -0700 | |
changeset 30 | 4fe00f5f71d9 |
parent 26 | 54f2f57cc0b0 |
permissions | -rw-r--r-- |
0 | 1 |
# -*- ruby -*- |
2 |
# vim: set noet nosta sw=4 ts=4 : |
|
3 |
#encoding: utf-8 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
4 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
5 |
require 'arborist/monitor' unless defined?( Arborist::Monitor ) |
14
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
6 |
require 'netsnmp' |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
7 |
|
0 | 8 |
# SNMP checks for Arborist. Requires an SNMP agent to be installed |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
9 |
# on target machine, and the various "pieces" enabled for your platform. |
0 | 10 |
# |
11 |
# For example, for disk monitoring with Net-SNMP, you'll want to set |
|
12 |
# 'includeAllDisks' in the snmpd.conf. bsnmpd on FreeBSD benefits from |
|
13 |
# the 'bsnmp-ucd' package. Etc. |
|
14 |
# |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
15 |
module Arborist::Monitor::SNMP |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
16 |
using Arborist::TimeRefinements |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
17 |
extend Configurability, Loggability |
0 | 18 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
19 |
# Loggability API |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
20 |
log_to :arborist_snmp |
0 | 21 |
|
7
4548e58c8c66
Use the new #node_properties method, convery from .rvmrc
Mahlon E. Smith <mahlon@martini.nu>
parents:
4
diff
changeset
|
22 |
# Always request the node addresses and any config. |
4548e58c8c66
Use the new #node_properties method, convery from .rvmrc
Mahlon E. Smith <mahlon@martini.nu>
parents:
4
diff
changeset
|
23 |
USED_PROPERTIES = [ :addresses, :config ].freeze |
4548e58c8c66
Use the new #node_properties method, convery from .rvmrc
Mahlon E. Smith <mahlon@martini.nu>
parents:
4
diff
changeset
|
24 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
25 |
# The OID that returns the system environment. |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
26 |
IDENTIFICATION_OID = '1.3.6.1.2.1.1.1.0' |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
27 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
28 |
# Global defaults for instances of this monitor |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
29 |
# |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
30 |
configurability( 'arborist.snmp' ) do |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
31 |
setting :timeout, default: 2 |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
32 |
setting :retries, default: 1 |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
33 |
setting :community, default: 'public' |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
34 |
setting :version, default: '2c' |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
35 |
setting :port, default: 161 |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
36 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
37 |
# How many hosts to check simultaneously |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
38 |
setting :batchsize, default: 25 |
7
4548e58c8c66
Use the new #node_properties method, convery from .rvmrc
Mahlon E. Smith <mahlon@martini.nu>
parents:
4
diff
changeset
|
39 |
end |
4548e58c8c66
Use the new #node_properties method, convery from .rvmrc
Mahlon E. Smith <mahlon@martini.nu>
parents:
4
diff
changeset
|
40 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
41 |
# The mapping of addresses back to node identifiers. |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
42 |
attr_reader :identifiers |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
43 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
44 |
# The results hash that is sent back to the manager. |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
45 |
attr_reader :results |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
46 |
|
0 | 47 |
|
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
48 |
### Connect to the SNMP daemon and yield. |
0 | 49 |
### |
50 |
def run( nodes ) |
|
51 |
||
1
8446f55f7e58
Allow local node "config" to override SNMP instanced globals. Add mount point includes and excludes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
0
diff
changeset
|
52 |
# Create mapping of addresses back to node identifiers, |
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
53 |
# and retain any custom (overrides) config per node. |
0 | 54 |
# |
1
8446f55f7e58
Allow local node "config" to override SNMP instanced globals. Add mount point includes and excludes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
0
diff
changeset
|
55 |
@identifiers = {} |
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
56 |
@results = {} |
1
8446f55f7e58
Allow local node "config" to override SNMP instanced globals. Add mount point includes and excludes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
0
diff
changeset
|
57 |
nodes.each_pair do |(identifier, props)| |
0 | 58 |
next unless props.key?( 'addresses' ) |
59 |
address = props[ 'addresses' ].first |
|
26
54f2f57cc0b0
Automatically clear stale mounts from node properties during disk checks.
Mahlon E. Smith <mahlon@martini.nu>
parents:
20
diff
changeset
|
60 |
self.identifiers[ address ] = [ identifier, props ] |
0 | 61 |
end |
62 |
||
63 |
# Perform the work! |
|
64 |
# |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
65 |
mainstart = Time.now |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
66 |
threads = ThreadGroup.new |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
67 |
batchcount = nodes.size / Arborist::Monitor::SNMP.batchsize |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
68 |
self.log.debug "Starting SNMP run for %d nodes" % [ nodes.size ] |
1
8446f55f7e58
Allow local node "config" to override SNMP instanced globals. Add mount point includes and excludes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
0
diff
changeset
|
69 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
70 |
self.identifiers.keys.each_slice( Arborist::Monitor::SNMP.batchsize ).each_with_index do |slice, batch| |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
71 |
slicestart = Time.now |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
72 |
self.log.debug " %d hosts (batch %d of %d)" % [ |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
73 |
slice.size, |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
74 |
batch + 1, |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
75 |
batchcount + 1 |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
76 |
] |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
77 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
78 |
slice.each do |host| |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
79 |
thr = Thread.new do |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
80 |
config = self.identifiers[ host ].last || {} |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
81 |
opts = { |
14
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
82 |
host: host, |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
83 |
port: config[ 'port' ] || Arborist::Monitor::SNMP.port, |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
84 |
version: config[ 'version' ] || Arborist::Monitor::SNMP.version, |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
85 |
community: config[ 'community' ] || Arborist::Monitor::SNMP.community, |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
86 |
timeout: config[ 'timeout' ] || Arborist::Monitor::SNMP.timeout, |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
87 |
retries: config[ 'retries' ] || Arborist::Monitor::SNMP.retries |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
88 |
} |
0 | 89 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
90 |
begin |
14
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
91 |
NETSNMP::Client.new( opts ) do |snmp| |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
92 |
Thread.current[ :system ] = snmp.get( oid: IDENTIFICATION_OID ) |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
93 |
yield( host, snmp ) |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
94 |
end |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
95 |
|
14
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
96 |
rescue => err |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
97 |
self.log.error "%s: %s\n%s" % [ host, err.message, err.backtrace.join("\n ") ] |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
98 |
self.results[ host ] = { |
14
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
99 |
error: "Exception (%s: %s)" % [ err.class.name, err.message ] |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
100 |
} |
0 | 101 |
end |
102 |
end |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
103 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
104 |
threads.add( thr ) |
0 | 105 |
end |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
106 |
|
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
107 |
# Wait for thread completions |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
108 |
threads.list.map( &:join ) |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
109 |
self.log.debug " finished after %0.1f seconds." % [ Time.now - slicestart ] |
0 | 110 |
end |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
111 |
self.log.debug "Completed SNMP run for %d nodes after %0.1f seconds." % [ nodes.size, Time.now - mainstart ] |
0 | 112 |
|
113 |
# Map everything back to identifier -> attribute(s), and send to the manager. |
|
114 |
# |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
115 |
reply = self.results.each_with_object({}) do |(address, results), hash| |
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
116 |
identifier = self.identifiers[ address ] or next |
3
d46ca2b52efe
Put the nil check back when building the results hash.
Mahlon E. Smith <mahlon@martini.nu>
parents:
1
diff
changeset
|
117 |
hash[ identifier.first ] = results |
0 | 118 |
end |
119 |
return reply |
|
120 |
||
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
121 |
ensure |
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
122 |
@identifiers = {} |
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
123 |
@results = {} |
0 | 124 |
end |
125 |
||
14
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
126 |
|
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
127 |
### Return the current SNMP connection system string. |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
128 |
def system |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
129 |
return Thread.current[ :system ] |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
130 |
end |
d5cb8bd33170
Although faster, once aiming a few thousand nodes at net-snmp2 it leaks memory like a sieve. Use 'netsnmp' instead.
Mahlon E. Smith <mahlon@martini.nu>
parents:
8
diff
changeset
|
131 |
|
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
132 |
end # Arborist::Monitor::SNMP |
0 | 133 |
|
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
134 |
require 'arborist/monitor/snmp/cpu' |
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
135 |
require 'arborist/monitor/snmp/disk' |
8
e0b7c95a154f
Refactor for real world usage and latest Arborist behaviors.
Mahlon E. Smith <mahlon@martini.nu>
parents:
7
diff
changeset
|
136 |
require 'arborist/monitor/snmp/process' |
4
e6eb11b1e00d
Refactor. Move all SNMP "sections" to their own classes.
Mahlon E. Smith <mahlon@martini.nu>
parents:
3
diff
changeset
|
137 |
require 'arborist/monitor/snmp/memory' |
20
00a38d493f2c
add UPS monitoring capability
Katelyn Schiesser <kschiesser@laika.com>
parents:
14
diff
changeset
|
138 |
require 'arborist/monitor/snmp/ups' |
00a38d493f2c
add UPS monitoring capability
Katelyn Schiesser <kschiesser@laika.com>
parents:
14
diff
changeset
|
139 |
require 'arborist/monitor/snmp/ups/battery' |
0 | 140 |