From 6c0dc7b66f2b95083673f0306b7f23a4d2604a12 Mon Sep 17 00:00:00 2001 From: Sebastien BLANCHET Date: Wed, 28 Aug 2024 12:41:26 +0200 Subject: [PATCH] Add support for UUID disk and serial number --- README | 7 ++++++ encled | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ encled.8 | 29 +++++++++++++++------- 3 files changed, 101 insertions(+), 8 deletions(-) diff --git a/README b/README index 3a40e78..7bfa51f 100644 --- a/README +++ b/README @@ -17,7 +17,12 @@ but empty disk slots too. enclosure led to 'FAULTY' status. encled enclosure/slot locate - set led indicator to 'locate' status encled enclosure/slot off - turn off faulty/locate status + encled enclosure/slot fault_off - turn off fault status + encled enclosure/slot locate_off - turn off locate status + encled device locate/fault/off will work with sd device (sda, sde) + encled uuid locate/fault/off will work with partuuid or disk uuid + encled serial locate/fault/off will work with disk serial number encled ALL off encled GOOD off - turns off leds only on devices where fault led is off @@ -31,3 +36,5 @@ but empty disk slots too. encled 5:0:24:0/12 locate - set location indicator for enclosure 5:0:24:0 slot 12 encled sda locate - enable 'locate' for slot with sda block device encled /dev/sdbz fault - enable fault indicator slot with sdbz block device + encled 3e61c7a8-deb6-11ed-92b5-00074371a6d0 locate - enable 'locate' for slot with this partition UUID + encled 8ABCDEF locate - enable 'locate' for slot with this disk serial number diff --git a/encled b/encled index 9f38892..2969905 100755 --- a/encled +++ b/encled @@ -1,5 +1,7 @@ #!/usr/bin/env python3 import os +import re +import subprocess import sys HELP = """ @@ -19,6 +21,8 @@ HELP = """ encled enclosure/slot locate_off - turn off locate status encled device locate/fault/off will work with sd device (sda, sde) + encled uuid locate/fault/off will work with partuuid or disk uuid + encled serial locate/fault/off will work with disk serial number encled ALL off encled GOOD off - turns off leds only on devices where fault led is off @@ -32,6 +36,8 @@ HELP = """ encled 5:0:24:0/12 locate - set location indicator for enclosure 5:0:24:0 slot 12 encled sda locate - enable 'locate' for slot with sda block device encled /dev/sdbz fault - enable fault indicator slot with sdbz block device + encled 3e61c7a8-deb6-11ed-92b5-00074371a6d0 locate - enable 'locate' for slot with this partition UUID + encled 8ABCDEF locate - enable 'locate' for slot with this disk serial number """ @@ -84,6 +90,62 @@ def find_name(enc, slot): name = '0' + name # try same name with more zeroes at front return None +def find_disk( a_disk_name ): + ''' + Explore /dev/sd* and /dev/disk/* to find hard disk device + If a hard disk is found then + return a string like "/dev/sdXX" + else + return None + ''' + # remove /dev prefix if any + a_disk_name = os.path.basename( a_disk_name ) + + # create subdirectory list from /dev/disk/* + disk_directories = [ os.path.join("/dev/disk/",d) for d in os.listdir("/dev/disk/") ] + disk_directories.append( "/dev/" ) + + for subdir_path in disk_directories: + files = os.listdir( subdir_path ) + for f in files: + if re.search(a_disk_name, f, re.IGNORECASE): # the file match + device_path = os.path.join(subdir_path, f) + absolute_device_path = os.path.realpath( device_path ) +# print( "Found %s" % absolute_path ) + + # remove trailing digits to get disk device instead of partition device + absolute_device_path = re.sub("\d+", "", absolute_device_path) + return absolute_device_path +# print( "INFO: the disk %s has not been found\n" % a_disk_name ) + return None + + +def find_serial( a_serial_number ): + ''' + Find hard disk device by serial number + if found + return sd device (for example /dev/sde) + else + return None + ''' + # use lsblk to get all the serial numbers + lsblk_command = '/usr/bin/lsblk --nodeps -o name,serial' + lsblk_output = subprocess.check_output( lsblk_command.split(" ") ) + lsblk_lines = lsblk_output.decode('utf-8').splitlines() + + # parse lsblk lines + for line in lsblk_lines: + tokens = line.rsplit() + if len(tokens) != 2: + continue # skip lines without serial number + blk_device, blk_serial = tuple(tokens) + # search a_serial_number in blk_serial + if re.search(a_serial_number, blk_serial, re.IGNORECASE): + return blk_device + +# print("INFO: the serial number %s has not been found" % a_serial_number) + return None + def get_status(path): ''' @@ -125,6 +187,9 @@ def set_status(path, status): Set status for given path status is 'fault' or 'locate' or 'off' ''' + # convert status to lower case + status = status.lower() + if status == 'fault': open(os.path.join(path, 'fault'), 'w').write('1') elif status == 'locate' or status == 'loc': @@ -197,6 +262,14 @@ def main(argv): if result: return(result) return(0) + # search disk device + disk_device = find_serial( argv[1] ) # by serial number + if not disk_device: + disk_device = find_disk( argv[1] ) # by /dev/disk/ + + if disk_device: # a hard disk device has been found + argv[1] = disk_device # overwrite argv[1] with + if 'sd' in argv[1] or '/dev' in argv[1]: name = argv[1].lower().split('/')[-1] for d in devlist: diff --git a/encled.8 b/encled.8 index af9a9eb..e31b27e 100644 --- a/encled.8 +++ b/encled.8 @@ -3,7 +3,7 @@ encled \- SCSI Enclosure indicators (SES LED) control .SH SYNOPSIS .B encled -[\fI\-\-help\fR] [\fIenclosure/slot|disk name|ALL\fR] [\fIlocate|fault|off\fR] +[\fI\-\-help\fR] [\fIenclosure/slot|disk_name|serial_number|ALL\fR] [\fIlocate|fault|off|locate_off|fault_off\fR] .SH DESCRIPTION .\" Add any additional description here Encled uses information in sysfs from ses.ko module to enumerate and control @@ -14,7 +14,7 @@ SES is SCSI Enclosure Services, specialized protocol between enclosure on hot-swap slots for disks. .SH INDICATION TYPES There is two types of indication: fault and locate. Third indication (activity) -unavailable for control from host. If one indicator is enabled, other is +is unavailable for control from host. If one indicator is enabled, other is automatically disabled. Keywords used: 'fault', 'locate' and 'off'. .SH ENUMERATION Enclosure enumeration is based on /sys/class/enclosure, and slot number is @@ -25,9 +25,18 @@ Note: Enumeration in encled may differ from sas2ircu or labels on the actual backplane. Don't rely on the slot numbers! .PP .SH DISK NAME -There is two ways to indicate disk in encled: by using drive name (/dev/sdaz) -or by using slot number (6:0:24:0/20). Special word 'all' is reserved for -controlling all indications (command 'encled all off' clears all indications). +There are several ways to indicate a disk in encled: +.IP \[bu] +by using drive name (/dev/sdaz) or a partition name (/dev/sdaz2) +.IP \[bu] +by using slot number (6:0:24:0/20) +.IP \[bu] +by using disk or partition UUID (/dev/disk/by-uuid or /dev/disk/by-partuuid) +.IP \[bu] +by using serial number. +.IP \[bu] +by using the special word 'all' to control all slots +(command 'encled all off' clears all indications). .SH EXAMPLES \fIencled /dev/sda fault\fR - enable fault indication for /dev/sda .br @@ -64,9 +73,13 @@ ENCLOSURE/SLOT DEV FAULT_LED LOCATION_LED .br 6:0:23:0/4 sdg FAULT_ON locate_off .SH NOTES -Encled supports only enclosure based devices (SAS/SATA). Desktop SATA controllers -(AHCI), and direct-attach disks in SCSI are not supported. -.br +.IP \[bu] +Encled supports only enclosure based devices (SAS/SATA). +.IP \[bu] +Desktop SATA controllers (AHCI), and direct-attach disks in SCSI are not supported. +.IP \[bu] +The software has been tested with Supermicro and AIC backplanes with LSI chips. +.IP \[bu] Older name for encled was sdled. .SH AUTHOR Written by George Shuklin