#!/usr/bin/env ruby

require 'snmp'
require 'trollop'

class CriticalStateException < StandardError; end

class CheckInodesSnmp
  def run
    if opts[:device]
      raise ArgumentError, "Device #{opts[:device]} not found" unless stats[opts[:device]]
      print 'INODES '

      if stats[opts[:device]] >= opts[:threshold]
        puts "CRITICAL: #{opts[:device]} #{stats[opts[:device]]}/100"
        raise CriticalStateException
      end

      puts "OK: #{opts[:device]} #{stats[opts[:device]]}/100"
    else
      critical_devices = stats.select { |_k, v| v >= opts[:threshold] }

      if critical_devices.any?
        print 'INODES CRITICAL:'
        critical_devices.each { |dev, val| print " #{dev} #{val}/100;" }
        puts
        raise CriticalStateException
      end

      puts 'INODES OK'
    end
  end

  def opts
    @opts ||= Trollop.options do
      opt :hostname,
          'Host to check',
          short: '-I',
          required: true,
          type: :string
      opt :threshold,
          'Threshold (percentage) above which to return an error',
          short: '-t',
          default: 80
      opt :device,
          'Device to check (default is to check everything)',
          short: '-d',
          type: :string
      opt :community,
          'Community string',
          short: '-c',
          default: 'public'
    end
  end

  def params
    {
      host: opts[:hostname],
      community: opts[:community],
      mib_modules: %w(UCD-SNMP-MIB)
    }
  end

  def stats
    @stats ||= begin
      columns = %w(dskPath dskPercentNode dskDevice)
      banned_fs = %w(proc sysfs none udev devpts tmpfs)
      collector = {}
      SNMP::Manager.open(params) do |manager|
        manager.walk(columns) do |row|
          collector[row[0].value] = row[1].value.to_i unless banned_fs.include?(row[2].value)
        end
      end
      collector
    end
  end
end

# rubocop:disable RescueException
begin
  CheckInodesSnmp.new.run
rescue CriticalStateException
  exit 2
rescue Exception => e
  puts e.message
  puts e.backtrace.join("\n")
  exit 3
end
# rubocop:enable RescueException
