[Libvir] PATCH: Add SCSI HBA backend for storage driver

Daniel P. Berrange berrange at redhat.com
Mon Mar 24 23:15:47 UTC 2008


And this time with the patch included...

 configure.in               |   28 ++
 src/Makefile.am            |   10 
 src/storage_backend.c      |   14 +
 src/storage_backend_scsi.c |  466 +++++++++++++++++++++++++++++++++++++++++++++
 src/storage_backend_scsi.h |   45 ++++
 src/storage_conf.c         |    9 
 src/util.c                 |    2 
 7 files changed, 571 insertions(+), 3 deletions(-)

Dan.

Index: configure.in
===================================================================
RCS file: /data/cvs/libvirt/configure.in,v
retrieving revision 1.136
diff -u -p -r1.136 configure.in
--- configure.in	21 Mar 2008 15:03:37 -0000	1.136
+++ configure.in	24 Mar 2008 23:05:25 -0000
@@ -28,6 +28,7 @@ GNUTLS_REQUIRED="1.0.25"
 AVAHI_REQUIRED="0.6.0"
 POLKIT_REQUIRED="0.6"
 PARTED_REQUIRED="1.8.0"
+HAL_REQUIRED="0.5.0"
 
 dnl Checks for C compiler.
 AC_PROG_CC
@@ -584,6 +585,8 @@ AC_ARG_WITH(storage-iscsi,
 [  --with-storage-iscsi        with iSCSI backend for the storage driver (on)],[],[with_storage_iscsi=check])
 AC_ARG_WITH(storage-disk,
 [  --with-storage-disk         with GPartd Disk backend for the storage driver (on)],[],[with_storage_disk=check])
+AC_ARG_WITH(storage-scsi,
+[  --with-storage-scsi         with HAL SCSI Disk backend for the storage driver (on)],[],[with_storage_scsi=check])
 
 if test "$with_storage_fs" = "yes" -o "$with_storage_fs" = "check"; then
   AC_PATH_PROG(MOUNT, [mount], [], [$PATH:/sbin:/usr/sbin])
@@ -741,6 +744,30 @@ AC_SUBST(LIBPARTED_CFLAGS)
 AC_SUBST(LIBPARTED_LIBS)
 
 
+HAL_CFLAGS=
+HAL_LIBS=
+if test "x$with_storage_scsi" = "xyes" -o "x$with_storage_scsi" = "xcheck"; then
+  PKG_CHECK_MODULES(HAL, hal >= $HAL_REQUIRED,
+    [with_storage_scsi=yes], [
+    if test "x$with_storage_scsi" = "xcheck" ; then
+       with_storage_scsi=no
+    else
+       AC_MSG_ERROR(
+         [You must install HAL >= $HAL_REQUIRED to compile libvirt])
+    fi
+  ])
+  if test "x$with_storage_scsi" = "xyes" ; then
+    AC_DEFINE_UNQUOTED(WITH_STORAGE_SCSI_, 1,
+      [use SCSI backend for storage driver is enabled])
+  fi
+fi
+AC_DEFINE_UNQUOTED(WITH_STORAGE_SCSI, 1, [whether SCSI backend for storage driver is enabled])
+AM_CONDITIONAL(WITH_STORAGE_SCSI, [test "yes" = "yes"])
+AC_SUBST(HAL_CFLAGS)
+AC_SUBST(HAL_LIBS)
+
+
+
 dnl
 dnl check for python
 dnl
@@ -968,6 +995,7 @@ AC_MSG_NOTICE([   NetFS: $with_storage_f
 AC_MSG_NOTICE([     LVM: $with_storage_lvm])
 AC_MSG_NOTICE([   iSCSI: $with_storage_iscsi])
 AC_MSG_NOTICE([    Disk: $with_storage_disk])
+AC_MSG_NOTICE([    SCSI: $with_storage_scsi])
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Libraries])
 AC_MSG_NOTICE([])
Index: src/Makefile.am
===================================================================
RCS file: /data/cvs/libvirt/src/Makefile.am,v
retrieving revision 1.75
diff -u -p -r1.75 Makefile.am
--- src/Makefile.am	21 Mar 2008 15:03:37 -0000	1.75
+++ src/Makefile.am	24 Mar 2008 23:05:25 -0000
@@ -9,6 +9,7 @@ INCLUDES = \
 	   $(GNUTLS_CFLAGS) \
 	   $(SASL_CFLAGS) \
 	   $(SELINUX_CFLAGS) \
+	   $(HAL_CFLAGS) \
 	   -DBINDIR=\""$(libexecdir)"\" \
 	   -DSBINDIR=\""$(sbindir)"\" \
 	   -DSYSCONF_DIR="\"$(sysconfdir)\"" \
@@ -89,11 +90,18 @@ else
 EXTRA_DIST += storage_backend_disk.h storage_backend_disk.c
 endif
 
+if WITH_STORAGE_SCSI
+CLIENT_SOURCES +=  storage_backend_scsi.h storage_backend_scsi.c
+else
+EXTRA_DIST +=  storage_backend_scsi.h storage_backend_scsi.c
+endif
+
 
 
 
 libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
-libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) $(SELINUX_LIBS) \
+libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) \
+                    $(SELINUX_LIBS) $(HAL_LIBS) \
 		    @CYGWIN_EXTRA_LIBADD@ ../gnulib/lib/libgnu.la
 libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \
                      -version-info @LIBVIRT_VERSION_INFO@ \
Index: src/storage_backend.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_backend.c,v
retrieving revision 1.10
diff -u -p -r1.10 storage_backend.c
--- src/storage_backend.c	17 Mar 2008 16:57:21 -0000	1.10
+++ src/storage_backend.c	24 Mar 2008 23:05:25 -0000
@@ -45,6 +45,9 @@
 #if WITH_STORAGE_DISK
 #include "storage_backend_disk.h"
 #endif
+#if WITH_STORAGE_SCSI
+#include "storage_backend_scsi.h"
+#endif
 
 
 #include "util.h"
@@ -67,6 +70,9 @@ static virStorageBackendPtr backends[] =
 #if WITH_STORAGE_DISK
     &virStorageBackendDisk,
 #endif
+#if WITH_STORAGE_SCSI
+    &virStorageBackendSCSI,
+#endif
 };
 
 
@@ -121,6 +127,10 @@ virStorageBackendFromString(const char *
     if (STREQ(type, "disk"))
         return VIR_STORAGE_POOL_DISK;
 #endif
+#if WITH_STORAGE_SCSI
+    if (STREQ(type, "scsi"))
+        return VIR_STORAGE_POOL_SCSI;
+#endif
 
     virStorageReportError(NULL, VIR_ERR_INTERNAL_ERROR,
                           _("unknown storage backend type %s"), type);
@@ -150,6 +160,10 @@ virStorageBackendToString(int type) {
     case VIR_STORAGE_POOL_DISK:
         return "disk";
 #endif
+#if WITH_STORAGE_SCSI
+    case VIR_STORAGE_POOL_SCSI:
+        return "scsi";
+#endif
     }
 
     virStorageReportError(NULL, VIR_ERR_INTERNAL_ERROR,
Index: src/storage_backend_scsi.c
===================================================================
RCS file: src/storage_backend_scsi.c
diff -N src/storage_backend_scsi.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/storage_backend_scsi.c	24 Mar 2008 23:05:25 -0000
@@ -0,0 +1,466 @@
+/*
+ * storage_backend_scsi.c: storage backend for SCSI handling
+ *
+ * Copyright (C) 2007-2008 Red Hat, Inc.
+ * Copyright (C) 2007-2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <unistd.h>
+#include <hal/libhal.h>
+
+#include "storage_backend_scsi.h"
+
+#define LINUX_SYSFS_SCSI_HOST_PREFIX "/sys/class/scsi_host/"
+#define LINUX_SYSFS_SCSI_HOST_POSTFIX "/device"
+
+
+/**
+ * virStorageBackendSCSIMakeHostDevice:
+ * @conn: report errors agains
+ * @pool: pool to resolve
+ * @buf: pre-allocated buffer to fill with path name
+ * @buflen: size of buffer
+ *
+ * Resolve a HBA name to HBA device  path
+ * 
+ * Given a pool object configured for a SCSI HBA, resolve the HBA name
+ * into the canonical sysfs path for the HBA device. This can then be
+ * used to lookup the device in HAL.
+ *
+ * Returns 0 on success, -1 on failure
+ */
+static int virStorageBackendSCSIMakeHostDevice(virConnectPtr conn,
+                                               virStoragePoolObjPtr pool,
+                                               char *buf,
+                                               size_t buflen)
+{
+    char *dev = NULL;
+    char *tmp = pool->def->source.adapter;
+    char relLink[PATH_MAX], absLink[PATH_MAX];
+    ssize_t len;
+
+    if (!tmp) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "Missing adapter name for pool");
+        return -1;
+    }
+
+    /* Sanity check host adapter name - should only be 0-9, a-z.
+     * Anything else is bogus & so we reject it, to prevent them
+     * making us read arbitrary paths on host
+     */
+    while (*tmp) {
+        if (!isalnum(*tmp)) {
+            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                  "Invalid character in pool adapter name '%s'",
+                                  pool->def->source.adapter);
+            return -1;
+        }
+        tmp++;
+    }
+
+    /*
+     * First get the class based path eg
+     *
+     *   /sys/class/scsi_host/host1/device
+     */
+    if ((dev = malloc(sizeof(LINUX_SYSFS_SCSI_HOST_PREFIX) +
+                      strlen(pool->def->source.adapter) +
+                      sizeof(LINUX_SYSFS_SCSI_HOST_POSTFIX) + 
+                      1)) == NULL) {
+        virStorageReportError(conn, VIR_ERR_NO_MEMORY,
+                              "pool device");
+        return -1;
+    }
+
+    strcpy(dev, LINUX_SYSFS_SCSI_HOST_PREFIX);
+    strcat(dev, pool->def->source.adapter);
+    strcat(dev, LINUX_SYSFS_SCSI_HOST_POSTFIX);
+
+    /*
+     * Now resolve the class based path symlink to the real
+     * device path, which is likely under PCI bus hierarchy
+     * and is the path tracked by HAL
+     */
+    /* Readlink does not null terminate, so we reserve one byte */
+    if ((len = readlink(dev, relLink, sizeof(relLink)-1)) < 0) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "cannot find SCSI host adapter '%s' at '%s'",
+                              pool->def->source.adapter, dev);
+        free(dev);
+        return -1;
+    }
+    relLink[len] = '\0';
+
+
+    /* 
+     * The symlink is relative, so now we have to turn it
+     * into a absolute path
+     */
+    if ((tmp = realloc(dev,
+                       sizeof(LINUX_SYSFS_SCSI_HOST_PREFIX) +
+                       strlen(pool->def->source.adapter) +
+                       1 + 
+                       strlen(relLink) +
+                       1)) == NULL) {
+        virStorageReportError(conn, VIR_ERR_NO_MEMORY,
+                              "pool device");
+        free(dev);
+        return -1;
+    }
+    dev = tmp;
+
+    strcpy(dev, LINUX_SYSFS_SCSI_HOST_PREFIX);
+    strcat(dev, pool->def->source.adapter);
+    strcat(dev, "/");
+    strcat(dev, relLink);
+    
+    /*
+     * And finally canonicalize the absolute path to remove the
+     * copious  ..  components
+     */
+    if (!realpath(dev, absLink)) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "cannot canonicalize link %s",
+                              strerror(errno));
+        free(dev);
+        return -1;
+    }
+    free(dev);
+
+    if (strlen(absLink) >= buflen) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "link too long for buffer");
+        return -1;
+    }
+    strcpy(buf, absLink);
+
+    return 0;
+}
+
+
+/**
+ * virStorageBackendSCSICreateVol
+ *
+ * Allocate a virStorageVolDef object for the specified
+ * metadata and hook it into the pool
+ *
+ * Returns 0 on success, -1 on failure
+ */
+static int
+virStorageBackendSCSICreateVol(virConnectPtr conn,
+                               virStoragePoolObjPtr pool,
+                               const char *name,
+                               const char *path,
+                               const char *key,
+                               unsigned long long size)
+{
+    virStorageVolDefPtr vol;
+    char *tmppath;
+
+    if ((vol = calloc(1, sizeof(*vol))) == NULL) {
+        virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("volume"));
+        goto cleanup;
+    }
+
+    tmppath = strdup(path);
+    vol->name = strdup(name);
+    vol->key = strdup(key);
+    vol->allocation = vol->capacity = size;
+
+    if ((vol->name == NULL) ||
+        (vol->key == NULL) ||
+        (tmppath == NULL)) {
+        virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("volume"));
+        goto cleanup;
+    }
+
+    /* Now figure out the stable path
+     *
+     * XXX this method is O(N) because it scans the pool target
+     * dir every time its run. Should figure out a more efficient
+     * way of doing this...
+     */
+    if ((vol->target.path = virStorageBackendStablePath(conn,
+                                                        pool,
+                                                        tmppath)) == NULL)
+        goto cleanup;
+
+    if (tmppath != vol->target.path)
+        free(tmppath);
+    tmppath = NULL;
+
+    if (virStorageBackendUpdateVolInfo(conn, vol, 0) < 0)
+        goto cleanup;
+
+    pool->def->capacity += vol->capacity;
+    pool->def->allocation += vol->allocation;
+
+    vol->next = pool->volumes;
+    pool->volumes = vol;
+    pool->nvolumes++;
+
+    return 0;
+
+ cleanup:
+    free(tmppath);
+    virStorageVolDefFree(vol);
+    return -1;
+}
+
+
+/**
+ * virStorageBackendSCSIAddLUN:
+ *
+ * @conn: connection to report errors against
+ * @pool: pool to register volume with
+ * @ctx: HAL context
+ * @devname: HAL device name for LUN
+ *
+ * Given a HAL device supported 'block' and 'storage' capabilities
+ * register it as a volume in the pool
+ *
+ * Returns 0 on success, -1 on error
+ */
+static int
+virStorageBackendSCSIAddLUN(virConnectPtr conn,
+                            virStoragePoolObjPtr pool,
+                            LibHalContext *ctx,
+                            const char *devname)
+{
+    char **strdevs = NULL;
+    int numstrdevs = 0;
+    char *dev = NULL, *key = NULL;
+    unsigned long long size;
+    int host, bus, target, lun;
+    int n = -1, i;
+    int ret = -1;
+    char name[100];
+    DBusError derr = DBUS_ERROR_INIT;
+
+    if ((strdevs = libhal_manager_find_device_string_match(ctx,
+                                                           "info.parent",
+                                                           devname,
+                                                           &numstrdevs,
+                                                           &derr)) == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to lookup LUNs for %s with HAL: %s",
+                              devname, derr.message);
+        goto cleanup;
+    }
+    for (i = 0 ; i < numstrdevs && n == -1 ; i++) {
+        char *cat = libhal_device_get_property_string(ctx,
+                                                      strdevs[0],
+                                                      "info.category",
+                                                      NULL);
+        /* XXX derr */
+        if (cat != NULL) {
+            if (STREQ(cat, "storage"))
+                n = i;
+            free(cat);
+        }
+    }
+    /* No storage vol for device - probably a removable vol so ignore */
+    if (n == -1) {
+        ret = 0;
+        goto cleanup;
+    }
+
+#define HAL_GET_PROPERTY(path, name, err, type, value)                  \
+    (value) = libhal_device_get_property_ ## type(ctx, (path), (name), (err)); \
+    if (dbus_error_is_set((err))) {                                     \
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,             \
+                              "unable to lookup '%s' property on %s: %s", \
+                              (name), (path), derr.message);            \
+        goto cleanup;                                                   \
+    }
+
+    /* These are props of the physical device */
+    HAL_GET_PROPERTY(devname, "scsi.host", &derr, int, host);
+    HAL_GET_PROPERTY(devname, "scsi.bus", &derr, int, bus);
+    HAL_GET_PROPERTY(devname, "scsi.target", &derr, int, target);
+    HAL_GET_PROPERTY(devname, "scsi.lun", &derr, int, lun);
+
+    /* These are props of the logic device */
+    HAL_GET_PROPERTY(strdevs[0], "block.device", &derr, string, dev);
+    /*
+     * XXX storage.serial is not actually unique if they have
+     * multipath on the fibre channel adapter
+     */
+    HAL_GET_PROPERTY(strdevs[0], "storage.serial", &derr, string, key);
+    HAL_GET_PROPERTY(strdevs[0], "storage.size", &derr, uint64, size);
+
+#undef HAL_GET_PROPERTY
+
+    snprintf(name, sizeof(name), "%d:%d:%d:%d", host, bus, target, lun);
+    name[sizeof(name)-1] = '\0';
+
+    if (virStorageBackendSCSICreateVol(conn, pool, name, dev, key, size) < 0)
+        goto cleanup;
+    ret = 0;
+
+ cleanup:
+    for (i = 0 ; strdevs && i < numstrdevs ; i++)
+        free(strdevs[i]);
+    free(strdevs);
+    free(dev);
+    free(key);
+    if (dbus_error_is_set(&derr))
+        dbus_error_free(&derr);
+    return ret;
+}
+
+
+/**
+ * virStorageBackendSCSIRefreshPool:
+ * 
+ * Query HAL for all storage devices associated with a specific
+ * SCSI HBA.
+ *
+ * XXX, currently we only support regular devices in /dev/,
+ * or /dev/disk/by-XXX.  In future we also need to be able to
+ * map to multipath devices setup under /dev/mpath/XXXX.
+ */
+static int
+virStorageBackendSCSIRefreshPool(virConnectPtr conn,
+                                 virStoragePoolObjPtr pool)
+{
+    char hostdevice[PATH_MAX];
+    LibHalContext *ctx = NULL;
+    DBusConnection *sysbus = NULL;
+    DBusError derr = DBUS_ERROR_INIT;
+    char **hbadevs = NULL, **blkdevs = NULL;
+    int numhbadevs = 0, numblkdevs = 0;
+    int i, ret = -1;
+
+    /* Get the canonical sysfs path for the HBA device */
+    if (virStorageBackendSCSIMakeHostDevice(conn, pool,
+                                            hostdevice, sizeof(hostdevice)) < 0)
+        goto cleanup;
+
+    if ((ctx = libhal_ctx_new()) == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to allocate HAL context");
+        goto cleanup;
+    }
+
+    sysbus = dbus_bus_get(DBUS_BUS_SYSTEM, &derr);
+    if (sysbus == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to get dbus system bus: %s",
+                              derr.message);
+        goto cleanup;
+    }
+
+    if (!libhal_ctx_set_dbus_connection(ctx, sysbus)) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to set HAL dbus connection");
+        goto cleanup;
+    }
+
+
+    if (!libhal_ctx_init(ctx, &derr)) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to initialize HAL context: %s",
+                              derr.message);
+        goto cleanup;
+    }
+
+    if ((hbadevs = libhal_manager_find_device_string_match(ctx,
+                                                           "linux.sysfs_path",
+                                                           hostdevice,
+                                                           &numhbadevs,
+                                                           &derr)) == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to lookup device %s with HAL: %s",
+                              hostdevice, derr.message);
+        goto cleanup;
+    }
+
+    if (numhbadevs != 1) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "unexpected number of HBA devices from HAL");
+        goto cleanup;
+    }
+
+    if ((blkdevs = libhal_manager_find_device_string_match(ctx,
+                                                           "info.parent",
+                                                           hbadevs[0],
+                                                           &numblkdevs,
+                                                           &derr)) == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "failed to lookup LUNs for %s with HAL: %s",
+                              hbadevs[0], derr.message);
+        goto cleanup;
+    }
+
+    for (i = 0 ; i < numblkdevs ; i++)
+        virStorageBackendSCSIAddLUN(conn,
+                                    pool,
+                                    ctx,
+                                    blkdevs[i]);
+        
+    ret = 0;
+
+ cleanup:
+    for (i = 0 ; hbadevs && i < numhbadevs ; i++)
+        free(hbadevs[i]);
+    free(hbadevs);
+    for (i = 0 ; blkdevs && i < numblkdevs ; i++)
+        free(blkdevs[i]);
+    free(blkdevs);
+    libhal_ctx_shutdown(ctx, NULL);
+    libhal_ctx_free(ctx);
+    if (sysbus)
+        dbus_connection_unref(sysbus);
+    if (dbus_error_is_set(&derr))
+        dbus_error_free(&derr);
+    return ret;
+}
+
+
+
+virStorageBackend virStorageBackendSCSI = {
+  .type = VIR_STORAGE_POOL_SCSI,
+
+  .refreshPool = virStorageBackendSCSIRefreshPool,
+
+  .poolOptions = {
+        .flags = (VIR_STORAGE_BACKEND_POOL_SOURCE_ADAPTER)
+    },
+  
+  .volType = VIR_STORAGE_VOL_BLOCK,
+};
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
Index: src/storage_backend_scsi.h
===================================================================
RCS file: src/storage_backend_scsi.h
diff -N src/storage_backend_scsi.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/storage_backend_scsi.h	24 Mar 2008 23:05:25 -0000
@@ -0,0 +1,45 @@
+/*
+ * storage_backend_scsi.h: storage backend for SCSI handling
+ *
+ * Copyright (C) 2007-2008 Red Hat, Inc.
+ * Copyright (C) 2007-2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#ifndef __VIR_STORAGE_BACKEND_SCSI_H__
+#define __VIR_STORAGE_BACKEND_SCSI_H__
+
+#include "storage_backend.h"
+
+extern virStorageBackend virStorageBackendSCSI;
+
+#endif /* __VIR_STORAGE_BACKEND_SCSI_H__ */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
Index: src/storage_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_conf.c,v
retrieving revision 1.3
diff -u -p -r1.3 storage_conf.c
--- src/storage_conf.c	27 Feb 2008 10:37:19 -0000	1.3
+++ src/storage_conf.c	24 Mar 2008 23:05:25 -0000
@@ -97,6 +97,7 @@ virStoragePoolDefFree(virStoragePoolDefP
     }
     free(def->source.devices);
     free(def->source.dir);
+    free(def->source.adapter);
 
     if (def->source.authType == VIR_STORAGE_POOL_AUTH_CHAP) {
         free(def->source.auth.chap.login);
@@ -320,6 +321,14 @@ virStoragePoolDefParseDoc(virConnectPtr 
         }
     }
 
+    if (options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_ADAPTER) {
+        if ((ret->source.adapter = virXPathString("string(/pool/source/adapter/@name)", ctxt)) == NULL) {
+            virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                                  "%s", _("missing source adapter"));
+            goto cleanup;
+        }
+    }
+
 
     authType = virXPathString("string(/pool/source/auth/@type)", ctxt);
     if (authType == NULL) {
Index: src/util.c
===================================================================
RCS file: /data/cvs/libvirt/src/util.c,v
retrieving revision 1.26
diff -u -p -r1.26 util.c
--- src/util.c	20 Mar 2008 11:24:30 -0000	1.26
+++ src/util.c	24 Mar 2008 23:05:25 -0000
@@ -443,8 +443,6 @@ int virFileLinkPointsTo(const char *chec
 
     /* compare */
     if (strcmp(checkReal, real) != 0) {
-        virLog("Link '%s' does not point to '%s', ignoring",
-               checkLink, checkReal);
         return 0;
     }
 


-- 
|: Red Hat, Engineering, Boston   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list