smart plugin: add option to store data using serial number
authorScott Talbert <scott.talbert@hgst.com>
Fri, 15 Jul 2016 14:14:28 +0000 (10:14 -0400)
committerScott Talbert <scott.talbert@hgst.com>
Fri, 15 Jul 2016 14:25:59 +0000 (10:25 -0400)
Since a device name (e.g., /dev/sda) can change, allow using the serial number
to store SMART data as this will ensure the data for a given drive is always
kept together.

src/collectd.conf.pod
src/smart.c

index 37a4d6b..fffef71 100644 (file)
@@ -6464,6 +6464,14 @@ from these disks anyway. This is useful in cases where libatasmart mistakenly
 reports disks as asleep because it has not been updated to incorporate support
 for newer idle states in the ATA spec.
 
+=item B<UseSerial> B<true>|B<false>
+
+A disk's kernel name (e.g., sda) can change from one boot to the next. If this
+option is enabled, the C<smart> plugin will use the disk's serial number (e.g.,
+HGST_HUH728080ALE600_2EJ8VH8X) instead of the kernel name as the key for
+storing data. This ensures that the data for a given disk will be kept together
+even if the kernel name changes.
+
 =back
 
 =head2 Plugin C<snmp>
index 45bfd17..33b9751 100644 (file)
@@ -36,13 +36,15 @@ static const char *config_keys[] =
 {
   "Disk",
   "IgnoreSelected",
-  "IgnoreSleepMode"
+  "IgnoreSleepMode",
+  "UseSerial"
 };
 
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static ignorelist_t *ignorelist = NULL;
 static int ignore_sleep_mode = 0;
+static int use_serial = 0;
 
 static int smart_config (const char *key, const char *value)
 {
@@ -67,6 +69,11 @@ static int smart_config (const char *key, const char *value)
     if (IS_TRUE (value))
       ignore_sleep_mode = 1;
   }
+  else if (strcasecmp ("UseSerial", key) == 0)
+  {
+    if (IS_TRUE (value))
+      use_serial = 1;
+  }
   else
   {
     return (-1);
@@ -137,7 +144,7 @@ static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedD
   }
 }
 
-static void smart_handle_disk (const char *dev)
+static void smart_handle_disk (const char *dev, const char *serial)
 {
   SkDisk *d = NULL;
   SkBool awake = FALSE;
@@ -146,9 +153,16 @@ static void smart_handle_disk (const char *dev)
   const SkSmartParsedData *spd;
   uint64_t poweron, powercycles, badsectors, temperature;
 
-  shortname = strrchr(dev, '/');
-  if (!shortname) return;
-  shortname++;
+  if (use_serial && serial)
+  {
+    shortname = serial;
+  }
+  else
+  {
+    shortname = strrchr(dev, '/');
+    if (!shortname) return;
+    shortname++;
+  }
   if (ignorelist_match (ignorelist, shortname) != 0) {
     DEBUG ("smart plugin: ignoring %s.", dev);
     return;
@@ -257,13 +271,14 @@ static int smart_read (void)
   devices = udev_enumerate_get_list_entry (enumerate);
   udev_list_entry_foreach (dev_list_entry, devices)
   {
-    const char *path, *devpath;
+    const char *path, *devpath, *serial;
     path = udev_list_entry_get_name (dev_list_entry);
     dev = udev_device_new_from_syspath (handle_udev, path);
     devpath = udev_device_get_devnode (dev);
+    serial = udev_device_get_property_value (dev, "ID_SERIAL");
 
     /* Query status with libatasmart */
-    smart_handle_disk (devpath);
+    smart_handle_disk (devpath, serial);
     udev_device_unref (dev);
   }