[libvirt] [PATCH v2] Improve SCSI volume key generation

Daniel P. Berrange berrange at redhat.com
Mon Apr 4 16:59:50 UTC 2011


An update of patch 10 from:

http://www.redhat.com/archives/libvir-list/2010-November/msg00555.html

The SCSI volumes get a better 'key' field based on the fully
qualified volume path. All SCSI volumes have a unique serial
available in hardware which can be obtained by sending a
suitable SCSI command. Call out to udev's 'scsi_id' command
to fetch this value

In v2:

 - Only use scsi_id if HAVE_UDEV is defined. This ensures
   use only on udev >= 145 and thus avoids problem of
   different semantics on RHEL-5 vintage udev
 - Use virCommandPtr instead of virExec
 - Use VIR_FDOPEN instead of fdopen

* src/storage/storage_backend_scsi.c: Improve volume key
  field value stability and uniqueness
---
 src/storage/storage_backend_scsi.c |   65 +++++++++++++++++++++++++++++++++--
 1 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index d880d65..ed91703 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -33,6 +33,7 @@
 #include "memory.h"
 #include "logging.h"
 #include "files.h"
+#include "command.h"
 
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
@@ -160,6 +161,65 @@ cleanup:
     return ret;
 }
 
+
+static char *
+virStorageBackendSCSISerial(const char *dev)
+{
+    char *serial = NULL;
+#ifdef HAVE_UDEV
+    int fd = -1;
+    FILE *list = NULL;
+    char line[1024];
+    virCommandPtr cmd = virCommandNewArgList(
+        "/lib/udev/scsi_id",
+        "--replace-whitespace",
+        "--whitelisted",
+        "--device", dev,
+        NULL
+        );
+
+    /* Run the program and capture its output */
+    virCommandSetOutputFD(cmd, &fd);
+    if (virCommandRunAsync(cmd, NULL) < 0)
+        goto cleanup;
+
+    if ((list = VIR_FDOPEN(fd, "r")) == NULL) {
+        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("cannot read fd"));
+        goto cleanup;
+    }
+
+    if (fgets(line, sizeof(line), list)) {
+        char *nl = strchr(line, '\n');
+        if (nl)
+            *nl = '\0';
+        VIR_ERROR("GOT ID %s\n", line);
+        serial = strdup(line);
+    } else {
+        VIR_ERROR("NO ID %s\n", dev);
+        serial = strdup(dev);
+    }
+
+    if (!serial) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+cleanup:
+    if (list)
+        fclose(list);
+    else
+        VIR_FORCE_CLOSE(fd);
+
+    virCommandFree(cmd);
+#else
+    if (!(serial = strdup(dev)))
+        virReportOOMError();
+#endif
+    return serial;
+}
+
+
 static int
 virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
                             uint32_t host ATTRIBUTE_UNUSED,
@@ -233,10 +293,7 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
         goto free_vol;
     }
 
-    /* XXX should use logical unit's UUID instead */
-    vol->key = strdup(vol->target.path);
-    if (vol->key == NULL) {
-        virReportOOMError();
+    if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) {
         retval = -1;
         goto free_vol;
     }
-- 
1.7.4




More information about the libvir-list mailing list