[libvirt] [PATCH 1/1] Merge DanPB's SCSI HBA pool code

David Allan dallan at redhat.com
Fri Feb 20 22:14:55 UTC 2009


Last March, DanPB posted code to create pools from SCSI HBAs.  This patch is simply bringing that code into the current tree.

* src/storage_backend_scsi.[ch] contain the pool implementataion
* There are small changes to several other source files to integrate the new pool type.
---
 configure.in               |   13 ++-
 po/POTFILES.in             |    1 +
 src/Makefile.am            |    9 +
 src/storage_backend.c      |    6 +
 src/storage_backend_scsi.c |  471 ++++++++++++++++++++++++++++++++++++++++++++
 src/storage_backend_scsi.h |   45 +++++
 src/storage_conf.c         |   18 ++
 7 files changed, 562 insertions(+), 1 deletions(-)
 create mode 100644 src/storage_backend_scsi.c
 create mode 100644 src/storage_backend_scsi.h

diff --git a/configure.in b/configure.in
index d2e8252..b88a7d5 100644
--- a/configure.in
+++ b/configure.in
@@ -739,6 +739,8 @@ AC_ARG_WITH([storage-lvm],
 [  --with-storage-lvm          with LVM backend for the storage driver (on)],[],[with_storage_lvm=check])
 AC_ARG_WITH([storage-iscsi],
 [  --with-storage-iscsi        with iSCSI backend for the storage driver (on)],[],[with_storage_iscsi=check])
+AC_ARG_WITH([storage-scsi],
+[  --with-storage-scsi         with SCSI backend for the storage driver (on)],[],[with_storage_scsi=check])
 AC_ARG_WITH([storage-disk],
 [  --with-storage-disk         with GPartd Disk backend for the storage driver (on)],[],[with_storage_disk=check])
 
@@ -748,6 +750,7 @@ if test "$with_libvirtd" = "no"; then
   with_storage_fs=no
   with_storage_lvm=no
   with_storage_iscsi=no
+  with_storage_scsi=no
   with_storage_disk=no
 fi
 if test "$with_storage_dir" = "yes" ; then
@@ -876,6 +879,13 @@ if test "$with_storage_iscsi" = "yes" -o "$with_storage_iscsi" = "check"; then
 fi
 AM_CONDITIONAL([WITH_STORAGE_ISCSI], [test "$with_storage_iscsi" = "yes"])
 
+if test "$with_storage_scsi" = "check"; then
+   with_storage_scsi=yes
+
+   AC_DEFINE_UNQUOTED([WITH_STORAGE_SCSI], 1,
+     [whether SCSI backend for storage driver is enabled])
+   AM_CONDITIONAL([WITH_STORAGE_SCSI], [test "$with_storage_scsi" = "yes"])
+fi
 
 
 LIBPARTED_CFLAGS=
@@ -1158,7 +1168,7 @@ LV_LIBTOOL_OBJDIR=${lt_cv_objdir-.}
 AC_SUBST([LV_LIBTOOL_OBJDIR])
 
 dnl HAL or DeviceKit library for host device enumeration
-HAL_REQUIRED=0.0
+HAL_REQUIRED=0.5.0
 HAL_CFLAGS=
 HAL_LIBS=
 AC_ARG_WITH([hal],
@@ -1312,6 +1322,7 @@ AC_MSG_NOTICE([      FS: $with_storage_fs])
 AC_MSG_NOTICE([   NetFS: $with_storage_fs])
 AC_MSG_NOTICE([     LVM: $with_storage_lvm])
 AC_MSG_NOTICE([   iSCSI: $with_storage_iscsi])
+AC_MSG_NOTICE([    SCSI: $with_storage_scsi])
 AC_MSG_NOTICE([    Disk: $with_storage_disk])
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Driver Loadable Modules])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 7461f93..4433183 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -27,6 +27,7 @@ src/storage_backend_disk.c
 src/storage_backend_fs.c
 src/storage_backend_iscsi.c
 src/storage_backend_logical.c
+src/storage_backend_scsi.c
 src/storage_conf.c
 src/storage_driver.c
 src/test.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 3a798d2..f1dd789 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ INCLUDES = \
 	   $(XEN_CFLAGS) \
 	   $(SELINUX_CFLAGS) \
 	   $(DRIVER_MODULE_CFLAGS) \
+	   $(POLKIT_CFLAGS) \
 	   -DLIBDIR=\""$(libdir)"\" \
 	   -DBINDIR=\""$(libexecdir)"\" \
 	   -DSBINDIR=\""$(sbindir)"\" \
@@ -158,6 +159,9 @@ STORAGE_DRIVER_LVM_SOURCES =					\
 STORAGE_DRIVER_ISCSI_SOURCES =					\
 		storage_backend_iscsi.h storage_backend_iscsi.c
 
+STORAGE_DRIVER_SCSI_SOURCES =					\
+		storage_backend_scsi.h storage_backend_scsi.c
+
 STORAGE_DRIVER_DISK_SOURCES =					\
 		storage_backend_disk.h storage_backend_disk.c
 
@@ -344,6 +348,10 @@ if WITH_STORAGE_ISCSI
 libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_ISCSI_SOURCES)
 endif
 
+if WITH_STORAGE_SCSI
+libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SCSI_SOURCES)
+endif
+
 if WITH_STORAGE_DISK
 libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_DISK_SOURCES)
 endif
@@ -392,6 +400,7 @@ EXTRA_DIST +=							\
 		$(STORAGE_DRIVER_FS_SOURCES)			\
 		$(STORAGE_DRIVER_LVM_SOURCES)			\
 		$(STORAGE_DRIVER_ISCSI_SOURCES)			\
+		$(STORAGE_DRIVER_SCSI_SOURCES)			\
 		$(STORAGE_DRIVER_DISK_SOURCES)			\
 		$(NODE_DEVICE_DRIVER_SOURCES)			\
 		$(NODE_DEVICE_DRIVER_HAL_SOURCES)		\
diff --git a/src/storage_backend.c b/src/storage_backend.c
index 8408f34..95173fa 100644
--- a/src/storage_backend.c
+++ b/src/storage_backend.c
@@ -54,6 +54,9 @@
 #if WITH_STORAGE_ISCSI
 #include "storage_backend_iscsi.h"
 #endif
+#if WITH_STORAGE_SCSI
+#include "storage_backend_scsi.h"
+#endif
 #if WITH_STORAGE_DISK
 #include "storage_backend_disk.h"
 #endif
@@ -78,6 +81,9 @@ static virStorageBackendPtr backends[] = {
 #if WITH_STORAGE_ISCSI
     &virStorageBackendISCSI,
 #endif
+#if WITH_STORAGE_SCSI
+    &virStorageBackendSCSI,
+#endif
 #if WITH_STORAGE_DISK
     &virStorageBackendDisk,
 #endif
diff --git a/src/storage_backend_scsi.c b/src/storage_backend_scsi.c
new file mode 100644
index 0000000..236d894
--- /dev/null
+++ b/src/storage_backend_scsi.c
@@ -0,0 +1,471 @@
+/*
+ * 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 redhat com>
+ */
+
+#include <config.h>
+
+#include <c-ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <hal/libhal.h>
+
+#include "virterror_internal.h"
+#include "storage_backend_scsi.h"
+#include "memory.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+#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 (!c_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) {
+        virReportOOMError(conn);
+        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) {
+        virReportOOMError(conn);
+        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)) {
+        char ebuf[1024];
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("cannot canonicalize link: %s"),
+                              virStrerror(errno, ebuf, sizeof ebuf));
+        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 (VIR_ALLOC(vol) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    vol->type = VIR_STORAGE_VOL_BLOCK;
+
+    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)) {
+        virReportOOMError(conn);
+        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, 1) < 0)
+        goto cleanup;
+
+    pool->def->capacity += vol->capacity;
+    pool->def->allocation += vol->allocation;
+
+    if (VIR_REALLOC_N(pool->volumes.objs,
+                      pool->volumes.count+1) < 0) {
+        virReportOOMError(conn);
+        virStorageVolDefFree(vol);
+        goto cleanup;
+    }
+    pool->volumes.objs[pool->volumes.count++] = vol;
+
+    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,
+                              _("HAL failed to lookup LUNs for '%s': %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,
+                              _("HAL failed to lookup device '%s': %s"),
+                              hostdevice, derr.message);
+        goto cleanup;
+    }
+
+    if (numhbadevs != 1) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("unexpected number of HBA devices from HAL "
+                                "(expected 1, got %d) when looking up device "
+                                "'%s'"), numhbadevs, hostdevice);
+        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,
+};
+
+/*
+ * 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:
+ */
diff --git a/src/storage_backend_scsi.h b/src/storage_backend_scsi.h
new file mode 100644
index 0000000..c912269
--- /dev/null
+++ b/src/storage_backend_scsi.h
@@ -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 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:
+ */
diff --git a/src/storage_conf.c b/src/storage_conf.c
index 70107a2..2ea6f8e 100644
--- a/src/storage_conf.c
+++ b/src/storage_conf.c
@@ -187,6 +187,14 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
             .formatToString = virStoragePoolFormatDiskTypeToString,
         }
     },
+    { .poolType = VIR_STORAGE_POOL_SCSI,
+      .poolOptions = {
+            .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
+        },
+      .volOptions = {
+            .formatToString = virStoragePoolFormatDiskTypeToString,
+        }
+    },
     { .poolType = VIR_STORAGE_POOL_DISK,
       .poolOptions = {
             .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
@@ -269,6 +277,7 @@ virStoragePoolSourceFree(virStoragePoolSourcePtr source) {
     VIR_FREE(source->devices);
     VIR_FREE(source->dir);
     VIR_FREE(source->name);
+    VIR_FREE(source->adapter);
 
     if (source->authType == VIR_STORAGE_POOL_AUTH_CHAP) {
         VIR_FREE(source->auth.chap.login);
@@ -550,6 +559,15 @@ virStoragePoolDefParseDoc(virConnectPtr conn,
         }
     }
 
+    if (options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) {
+        if ((ret->source.adapter = virXPathString(conn,
+                                                  "string(/pool/source/adapter/@name)",
+                                                  ctxt)) == NULL) {
+            virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                             "%s", _("missing storage pool source adapter name"));
+            goto cleanup;
+        }
+    }
 
     authType = virXPathString(conn, "string(/pool/source/auth/@type)", ctxt);
     if (authType == NULL) {
-- 
1.6.0.6




More information about the libvir-list mailing list