[libvirt] [PATCH] Add APIs for obtaining the unique ID of LVM & SCSI volumes

From: "Daniel P. Berrange" <berrange@redhat.com> Both LVM volumes and SCSI LUNs have a globally unique identifier associated with them. It is useful to be able to query this identifier to then perform disk locking, rather than try to figure out a stable pathname. --- src/util/storage_file.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util/storage_file.h | 3 ++ 2 files changed, 96 insertions(+) diff --git a/src/util/storage_file.c b/src/util/storage_file.c index f38aa8e..56fd322 100644 --- a/src/util/storage_file.c +++ b/src/util/storage_file.c @@ -24,6 +24,7 @@ #include <config.h> #include "storage_file.h" +#include <command.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> @@ -38,6 +39,7 @@ #include "virterror_internal.h" #include "logging.h" #include "virfile.h" +#include "c-ctype.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -1073,3 +1075,94 @@ int virStorageFileIsClusterFS(const char *path) VIR_STORAGE_FILE_SHFS_GFS2 | VIR_STORAGE_FILE_SHFS_OCFS); } + +#ifdef LVS +const char *virStorageFileGetLVMKey(const char *path) +{ + /* + * # lvs --noheadings --unbuffered --nosuffix --options "uuid" LVNAME + * 06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky + */ + char *key = NULL; + virCommandPtr cmd = virCommandNewArgList( + LVS, + "--noheadings", "--unbuffered", "--nosuffix", + "--options", "uuid", path, + NULL + ); + + /* Run the program and capture its output */ + virCommandSetOutputBuffer(cmd, &key); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + if (key) { + char *nl; + char *tmp = key; + + /* Find first non-space character */ + while (*tmp && c_isspace(*tmp)) { + tmp++; + } + /* Kill leading spaces */ + if (tmp != key) + memmove(key, tmp, strlen(tmp)+1); + + /* Kill trailing newline */ + if ((nl = strchr(key, '\n'))) + *nl = '\0'; + } + + if (key && STREQ(key, "")) + VIR_FREE(key); + +cleanup: + virCommandFree(cmd); + + return key; +} +#else +const char *virStorageFileGetLVMKey(const char *path) +{ + virReportSystemError(ENOSYS, _("Unable to get LVM key for %s"), path); + return NULL; +} +#endif + +#ifdef HAVE_UDEV +const char *virStorageFileGetSCSIKey(const char *path) +{ + char *key = NULL; + virCommandPtr cmd = virCommandNewArgList( + "/lib/udev/scsi_id", + "--replace-whitespace", + "--whitelisted", + "--device", path, + NULL + ); + + /* Run the program and capture its output */ + virCommandSetOutputBuffer(cmd, &key); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + if (key && STRNEQ(key, "")) { + char *nl = strchr(key, '\n'); + if (nl) + *nl = '\0'; + } else { + VIR_FREE(key); + } + +cleanup: + virCommandFree(cmd); + + return key; +} +#else +const char *virStorageFileGetSCSIKey(const char *path) +{ + virReportSystemError(ENOSYS, _("Unable to get SCSI key for %s"), path); + return NULL; +} +#endif diff --git a/src/util/storage_file.h b/src/util/storage_file.h index 1fbe08e..99a5e36 100644 --- a/src/util/storage_file.h +++ b/src/util/storage_file.h @@ -86,4 +86,7 @@ int virStorageFileIsClusterFS(const char *path); int virStorageFileIsSharedFSType(const char *path, int fstypes); +const char *virStorageFileGetLVMKey(const char *path); +const char *virStorageFileGetSCSIKey(const char *path); + #endif /* __VIR_STORAGE_FILE_H__ */ -- 1.7.11.2

On Thu, Aug 2, 2012 at 8:09 AM, Daniel P. Berrange <berrange@redhat.com> wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Both LVM volumes and SCSI LUNs have a globally unique identifier associated with them. It is useful to be able to query this identifier to then perform disk locking, rather than try to figure out a stable pathname. --
Would it not be better to call methods from within libdevmapper and libblkid than relying on a callout? Its also worth noting that iSCSI provides a GUID for the volume as well. -- Doug Goldstein

On Thu, Aug 02, 2012 at 11:32:14PM -0500, Doug Goldstein wrote:
On Thu, Aug 2, 2012 at 8:09 AM, Daniel P. Berrange <berrange@redhat.com> wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Both LVM volumes and SCSI LUNs have a globally unique identifier associated with them. It is useful to be able to query this identifier to then perform disk locking, rather than try to figure out a stable pathname. --
Would it not be better to call methods from within libdevmapper and libblkid than relying on a callout? Its also worth noting that iSCSI provides a GUID for the volume as well.
AFAICT, libblkid does not provide a way to get the SCSI WWN/Serial values. For iSCSI, I'm assuming that the devices just report the data using the regular kernel SCSI ioctls, so scsi_id should 'just work' already. That said, I think I might implement the SCSI lookup directly because I know remember previous discussions about the fact that the scsi_id command changed its supported command line arguments over time. I might try libdevmapper, if I can figure out its crazy API Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Fri, Aug 03, 2012 at 04:03:55PM +0100, Daniel P. Berrange wrote:
On Thu, Aug 02, 2012 at 11:32:14PM -0500, Doug Goldstein wrote:
On Thu, Aug 2, 2012 at 8:09 AM, Daniel P. Berrange <berrange@redhat.com> wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Both LVM volumes and SCSI LUNs have a globally unique identifier associated with them. It is useful to be able to query this identifier to then perform disk locking, rather than try to figure out a stable pathname. --
Would it not be better to call methods from within libdevmapper and libblkid than relying on a callout? Its also worth noting that iSCSI provides a GUID for the volume as well.
AFAICT, libblkid does not provide a way to get the SCSI WWN/Serial values. For iSCSI, I'm assuming that the devices just report the data using the regular kernel SCSI ioctls, so scsi_id should 'just work' already.
Issuing SCSI ioctls would indeed be possible, but the code is not entirely trivial. I looked to see if sg3utils provided a nice API for this, and while they do have APIs for dealing with SCSI commands, all the code for actually interpreting the data is still in their command line tools under GPL license, so that's not good. Since we already invoke this scsi_id command from the storage drivers, what I have here is no worse. So I'm shelfing the idea of doing SCSI directly until I (or someone else) has more time
That said, I think I might implement the SCSI lookup directly because I know remember previous discussions about the fact that the scsi_id command changed its supported command line arguments over time.
I might try libdevmapper, if I can figure out its crazy API
Well, the API is even more crazy that I expected, so I'm not going to change this patch now. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 08/02/2012 07:09 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Both LVM volumes and SCSI LUNs have a globally unique identifier associated with them. It is useful to be able to query this identifier to then perform disk locking, rather than try to figure out a stable pathname. --- src/util/storage_file.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util/storage_file.h | 3 ++ 2 files changed, 96 insertions(+)
+#ifdef HAVE_UDEV +const char *virStorageFileGetSCSIKey(const char *path) +{ + char *key = NULL; + virCommandPtr cmd = virCommandNewArgList( + "/lib/udev/scsi_id",
Are we okay hard-coding the name of this utility, or should it be learned during configure? At any rate, changing that can be an incremental improvement later. ACK. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Mon, Aug 06, 2012 at 02:16:39PM -0600, Eric Blake wrote:
On 08/02/2012 07:09 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Both LVM volumes and SCSI LUNs have a globally unique identifier associated with them. It is useful to be able to query this identifier to then perform disk locking, rather than try to figure out a stable pathname. --- src/util/storage_file.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util/storage_file.h | 3 ++ 2 files changed, 96 insertions(+)
+#ifdef HAVE_UDEV +const char *virStorageFileGetSCSIKey(const char *path) +{ + char *key = NULL; + virCommandPtr cmd = virCommandNewArgList( + "/lib/udev/scsi_id",
Are we okay hard-coding the name of this utility, or should it be learned during configure? At any rate, changing that can be an incremental improvement later.
AFAIK, it is always in this location on all distros, so I think we're safe for now. NB, this is the same as some code already present in the storage driver source - I'll be sending a followup patch to make the storage driver just call this method now.
ACK.
Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
Doug Goldstein
-
Eric Blake