diff options
Diffstat (limited to 'cmd/zed/zed.d/statechange-led.sh')
-rwxr-xr-x | cmd/zed/zed.d/statechange-led.sh | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/cmd/zed/zed.d/statechange-led.sh b/cmd/zed/zed.d/statechange-led.sh new file mode 100755 index 000000000..ca911d2b9 --- /dev/null +++ b/cmd/zed/zed.d/statechange-led.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# +# Turn off/on the VDEV's enclosure fault LEDs when the pool's state changes. +# +# Turn LED on if the VDEV becomes faulted/degraded, and turn it back off when +# it's healthy again. This requires that your enclosure be supported by the +# Linux SCSI enclosure services (ses) driver. The script will do nothing +# if you have no enclosure, or if your enclosure isn't supported. +# +# This script also requires ZFS to be built with libdevmapper support. +# +# Exit codes: +# 0: enclosure led successfully set +# 1: enclosure leds not not available +# 2: enclosure leds administratively disabled +# 3: ZED built without libdevmapper + +[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" +. "${ZED_ZEDLET_DIR}/zed-functions.sh" + +# ZEVENT_VDEV_UPATH will not be present if ZFS is not built with libdevmapper +[ -n "${ZEVENT_VDEV_UPATH}" ] || exit 3 + +if [ "${ZED_USE_ENCLOSURE_LEDS}" != "1" ] ; then + exit 2 +fi + +if [ ! -d /sys/class/enclosure ] ; then + exit 1 +fi + +# Turn on/off enclosure LEDs +function led +{ + name=$1 + val=$2 + + # We want to check the current state first, since writing to the + # 'fault' entry always always causes a SES command, even if the + # current state is already what you want. + if [ -e /sys/block/$name/device/enclosure_device*/fault ] ; then + # We have to do some monkey business to deal with spaces in + # enclosure_device names. I've seen horrible things like this: + # + # '/sys/block/sdfw/device/enclosure_device:SLOT 43 41 /fault' + # + # ...so escape all spaces. + file=`ls /sys/block/$name/device/enclosure_device*/fault | sed 's/\s/\\ /g'` + + current=`cat "$file"` + + # On some enclosures if you write 1 to fault, and read it back, + # it will return 2. Treat all non-zero values as 1 for + # simplicity. + if [ "$current" != "0" ] ; then + current=1 + fi + + if [ "$current" != "$val" ] ; then + # Set the value twice. I've seen enclosures that were + # flakey about setting it the first time. + echo $val > "$file" + echo $val > "$file" + fi + fi +} + +# Decide whether to turn on/off an LED based on the state +# Pass in path name and fault string ("ONLINE"/"FAULTED"/"DEGRADED"...etc) +function process { + # path=/dev/sda, fault= + + path=$1 + fault=$2 + name=`basename $path` + + if [ -z "$name" ] ; then + return + fi + + if [ "$fault" == "FAULTED" ] || [ "$fault" == "DEGRADED" ] ; then + led $name 1 + else + led $name 0 + fi +} + +process "$ZEVENT_VDEV_UPATH" "$ZEVENT_VDEV_STATE_STR" |