diff -r 54f2f57cc0b0 -r 02b8e772e0c5 lib/arborist/monitor/snmp/disk.rb --- a/lib/arborist/monitor/snmp/disk.rb Tue Apr 28 10:10:19 2020 -0700 +++ b/lib/arborist/monitor/snmp/disk.rb Mon Jul 27 03:19:20 2020 -0700 @@ -19,7 +19,8 @@ STORAGE_NET_SNMP = { path: '1.3.6.1.4.1.2021.9.1.2', percent: '1.3.6.1.4.1.2021.9.1.9', - type: '1.3.6.1.2.1.25.3.8.1.4' + type: '1.3.6.1.2.1.25.3.8.1.4', + access: '1.3.6.1.2.1.25.3.8.1.5' } # The OID that matches a local windows hard disk. @@ -41,6 +42,9 @@ # The fallback warning capacity. WARN_AT = 90 + # Access mode meanings + ACCESS_READWRITE = 1 + ACCESS_READONLY = 2 # Configurability API # @@ -64,6 +68,12 @@ mounts = Array( val ).map{|m| Regexp.new(m) } Regexp.union( mounts ) end + + # Paths to alert for read-only status + setting :readonly_include, default: [ '^/$' ] do |val| + mounts = Array( val ).map{|m| Regexp.new(m) } + Regexp.union( mounts ) + end end @@ -104,34 +114,38 @@ config = self.identifiers[ host ].last['config'] || {} warn_at = config[ 'warn_at' ] || self.class.warn_at - self.log.warn self.identifiers[ host ] + self.log.debug self.identifiers[ host ] includes = self.format_mounts( config, 'include' ) || self.class.include excludes = self.format_mounts( config, 'exclude' ) || self.class.exclude - current_mounts.reject! do |path, percentage| + current_mounts.reject! do |path, data| path = path.to_s excludes.match( path ) || ( includes && ! includes.match( path ) ) end errors = [] warnings = [] - current_mounts.each_pair do |path, percentage| + current_mounts.each_pair do |path, data| warn = if warn_at.is_a?( Hash ) warn_at[ path ] || WARN_AT else warn_at end - self.log.debug "%s:%s -> at %d, warn at %d" % [ host, path, percentage, warn ] + self.log.debug "%s:%s -> %p, warn at %d" % [ host, path, data, warn ] - if percentage >= warn.to_i - if percentage >= 100 - errors << "%s at %d%% capacity" % [ path, percentage ] + if data[ :capacity ] >= warn.to_i + if data[ :capacity ] >= 100 + errors << "%s at %d%% capacity" % [ path, data[ :capacity ] ] else - warnings << "%s at %d%% capacity" % [ path, percentage ] + warnings << "%s at %d%% capacity" % [ path, data[ :capacity ] ] end end + + if self.class.readonly_include.match( path ) && data[ :accessmode ] == ACCESS_READONLY + errors << "%s is mounted read-only." % [ path ] + end end # Remove any past mounts that configuration exclusions should @@ -185,7 +199,7 @@ next if totals[ idx ].zero? next unless types[ idx ] disks[ path ] ||= {} - disks[ path ] = (( used[idx].to_f / totals[idx] ) * 100).round( 1 ) + disks[ path ][ :capacity ] = (( used[idx].to_f / totals[idx] ) * 100).round( 1 ) end return disks @@ -195,16 +209,21 @@ ### Fetch information for Unix/MacOS systems. ### def unix_disks( snmp ) - oids = [ STORAGE_NET_SNMP[:path], STORAGE_NET_SNMP[:percent] ] - paths = snmp.walk( oid: oids.first ).each_with_object( [] ) do |(_, value), acc| + oids = [ STORAGE_NET_SNMP[:path], STORAGE_NET_SNMP[:percent], STORAGE_NET_SNMP[:access] ] + paths = snmp.walk( oid: STORAGE_NET_SNMP[:path] ).each_with_object( [] ) do |(_, value), acc| acc << value end - capacities = snmp.walk( oid: oids.last ).each_with_object( [] ) do |(_, value), acc| + capacities = snmp.walk( oid: STORAGE_NET_SNMP[:percent] ).each_with_object( [] ) do |(_, value), acc| + acc << value + end + accessmodes = snmp.walk( oid: STORAGE_NET_SNMP[:access] ).each_with_object( [] ) do |(_, value), acc| acc << value end - pairs = paths.zip( capacities ) - return Hash[ *pairs.flatten ] + pairs = paths.each_with_object( {} ).with_index do |(p, acc), idx| + acc[p] = { capacity: capacities[idx], accessmode: accessmodes[idx] } + end + return pairs end end # class Arborist::Monitor::SNMP::Disk