Skip to content

Instantly share code, notes, and snippets.

@lcx
Created July 13, 2017 08:52
Show Gist options
  • Save lcx/9e6ce9f2beec58c078217b8be6441a12 to your computer and use it in GitHub Desktop.
Save lcx/9e6ce9f2beec58c078217b8be6441a12 to your computer and use it in GitHub Desktop.
#! /usr/bin/env ruby
# encoding: UTF-8
#
# check-smart
#
# DESCRIPTION:
#
# OUTPUT:
# plain text
#
# PLATFORMS:
# Linux
#
# DEPENDENCIES:
# gem: sensu-plugin
#
# USAGE:
#
# NOTES:
# This is a drop-in replacement for check-disk-health.sh.
#
# smartctl requires root permissions. When running this script as a non-root
# user such as sensu, ensure it is run with sudo.
#
# Create a file named /etc/sudoers.d/smartctl with this line inside :
# sensu ALL=(ALL) NOPASSWD: /usr/sbin/smartctl
# sensu ALL=(ALL) NOPASSWD: /usr/sbin/storcli
#
# Fedora has some additional restrictions : if requiretty is set, sudo will only
# run when the user is logged in to a real tty.
# Then add this in the sudoers file (/etc/sudoers), below the line Defaults requiretty :
# Defaults sensu !requiretty
#
# LICENSE:
# Copyright 2013 Mitsutoshi Aoe <maoe@foldr.in>
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
#
require 'sensu-plugin/check/cli'
require 'json'
#
# Disk
#
class Disk
# Setup variables
#
def initialize(device_id)
@device_path = "-d megaraid,#{device_id} /dev/sda"
@smart_available = false
@smart_enabled = false
@smart_healty = nil
check_smart_capability!
check_health! if smart_capable?
end
attr_reader :capability_output, :health_output, :smart_healthy
alias healthy? smart_healthy
# Is the device SMART capable and enabled
#
def smart_capable?
@smart_available && @smart_enabled
end
# Check for SMART cspability
#
def check_smart_capability!
output = `sudo smartctl -i #{@device_path}`
@smart_available = !output.scan(/SMART support is:\s+Available/).empty?
@smart_enabled = !output.scan(/SMART support is:\s+Enabled/).empty?
@capability_output = output
end
# Check the SMART health
#
def check_health!
output = `sudo smartctl -H #{@device_path}`
@smart_healthy = !output.scan(/SMART Health Status: OK/).empty?
@health_output = output
end
end
#
# Check SMART
#
class CheckSMART < Sensu::Plugin::Check::CLI
option :smart_incapable_disks,
long: '--smart-incapable-disks EXIT_CODE',
description: 'Exit code when SMART is unavailable/disabled on a disk (ok, warn, critical, unknown)',
proc: proc(&:to_sym),
default: :unknown
# Setup variables
#
def initialize
super
@devices = []
scan_disks!
end
# Generate a list of all block devices
#
def scan_disks!
output = `sudo /usr/sbin/storcli /c0 /eall /sall show J`
parsed_output = JSON.parse(output)
critical "Can't get device ID from storcli" unless parsed_output["Controllers"][0]["Command Status"]["Status"]=="Success"
parsed_output["Controllers"][0]["Response Data"]["Drive Information"].each do |drive|
@devices << Disk.new(drive["DID"])
end
end
# Main function
#
def run
unknown 'No SMART capable devices found' unless @devices.length > 0
unhealthy_disks = @devices.select { |disk| disk.smart_capable? && !disk.healthy? }
unknown_disks = @devices.reject(&:smart_capable?)
if unhealthy_disks.length > 0
output = unhealthy_disks.map(&:health_output)
output.concat(unknown_disks.map(&:capability_output))
critical output.join("\n")
end
if unknown_disks.length > 0
exit_with(
config[:smart_incapable_disks],
unknown_disks.map(&:capability_output).join("\n")
)
end
ok 'PASSED'
end
# Set exit status and message
#
def exit_with(sym, message)
case sym
when :ok
ok message
when :warn
warn message
when :critical
critical message
else
unknown message
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment