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(a)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(a)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 :|