[libvirt] libvirt [PATCHv2 2/2] Add iSCSI backend storage driver for ESX.
by Ata E Husain Bohra
The patch adds the backend driver to support iSCSI format storage pools
and volumes for ESX host. The mapping of ESX iSCSI specifics to Libvirt
is as follows:
1. ESX static iSCSI target <------> Libvirt Storage Pools
2. ESX iSCSI LUNs <------> Libvirt Storage Volumes.
The above understanding is based on http://libvirt.org/storage.html.
The operation supported on iSCSI pools includes:
1. List storage pools & volumes.
2. Get xml descriptor operaion on pools & volumes.
3. Lookup operation on pools & volumes by name, uuid and path (if applicable).
iSCSI pools does not support operations such as: Create / remove pools
and volumes.
---
src/Makefile.am | 1 +
src/esx/esx_storage_backend_iscsi.c | 807 +++++++++++++++++++++++++++++++++++
src/esx/esx_storage_backend_iscsi.h | 29 ++
src/esx/esx_storage_driver.c | 8 +-
src/esx/esx_vi.c | 332 ++++++++++++++
src/esx/esx_vi.h | 18 +
src/esx/esx_vi_generator.input | 302 +++++++++++++
src/esx/esx_vi_generator.py | 19 +
8 files changed, 1515 insertions(+), 1 deletion(-)
create mode 100644 src/esx/esx_storage_backend_iscsi.c
create mode 100644 src/esx/esx_storage_backend_iscsi.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 4026a15..1668b84 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -494,6 +494,7 @@ ESX_DRIVER_SOURCES = \
esx/esx_network_driver.c esx/esx_network_driver.h \
esx/esx_storage_driver.c esx/esx_storage_driver.h \
esx/esx_storage_backend_vmfs.c esx/esx_storage_backend_vmfs.h \
+ esx/esx_storage_backend_iscsi.c esx/esx_storage_backend_iscsi.h \
esx/esx_device_monitor.c esx/esx_device_monitor.h \
esx/esx_secret_driver.c esx/esx_secret_driver.h \
esx/esx_nwfilter_driver.c esx/esx_nwfilter_driver.h \
diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c
new file mode 100644
index 0000000..fa4bf45
--- /dev/null
+++ b/src/esx/esx_storage_backend_iscsi.c
@@ -0,0 +1,807 @@
+/*
+ * esx_storage_backend_iscsi.c: ESX storage backend for iSCSI handling
+ *
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "internal.h"
+#include "md5.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+
+#include "storage_conf.h"
+#include "storage_file.h"
+#include "esx_storage_backend_iscsi.h"
+#include "esx_private.h"
+#include "esx_vi.h"
+#include "esx_vi_methods.h"
+#include "esx_util.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+/*
+ * The UUID of a storage pool is the MD5 sum of it's mount path. Therefore,
+ * verify that UUID and MD5 sum match in size, because we rely on that.
+ */
+verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
+
+
+
+static int
+esxStorageBackendISCSINumberOfStoragePools(virConnectPtr conn)
+{
+ int count = 0;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ bool success = false;
+
+ if (esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to obtain iSCSI adapter"));
+ goto cleanup;
+ }
+
+ /* FIXME: code looks for software iSCSI adapter only */
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return 0;
+ }
+
+ /**
+ * ESX has two kind of targets:
+ * 1. staticIscsiTargets
+ * 2. dynamicIscsiTargets
+ * For each dynamic target if its reachable a static target is added.
+ * return iSCSI names for all static targets to avoid duplicate names.
+ */
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ ++count;
+ }
+
+ success = true;
+
+cleanup:
+
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return success ? count : -1;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIListStoragePools(virConnectPtr conn,
+ char **const names,
+ const int maxnames)
+{
+ int count = 0;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ bool success = false;
+ int i = 0;
+
+ if (maxnames ==0) {
+ return 0;
+ }
+
+ if (esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to obtain iSCSI adapter"));
+ goto cleanup;
+ }
+
+ /* FIXME: code looks for software iSCSI adapter only */
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return 0;
+ }
+
+ /**
+ * ESX has two kind of targets:
+ * 1. staticIscsiTargets
+ * 2. dynamicIscsiTargets
+ * For each dynamic target if its reachable a static target is added.
+ * return iSCSI names for all static targets to avoid duplicate names.
+ */
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL && count < maxnames;
+ target = target->_next, ++count) {
+ names[count] = strdup(target->iScsiName);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ success = true;
+
+cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return success ? count : -1;
+}
+
+
+
+static virStoragePoolPtr
+esxStorageBackendISCSIPoolLookupByName(virConnectPtr conn,
+ const char *name)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ virStoragePoolPtr pool = NULL;
+
+ /* lookup routine are used by the base driver to determine
+ * appropriate backend driver, lookup targetName as optional
+ * parameter
+ */
+ if (esxVI_LookupHostInternetScsiHbaStaticTargetByName(
+ priv->primary, name, &target, esxVI_Occurrence_OptionalItem) < 0 ||
+ target == NULL) {
+ goto cleanup;
+ }
+
+ /**
+ * HostInternetScsiHbaStaticTarget does not provide a uuid field,
+ * but iScsiName (or widely known as IQN) is unique across the multiple
+ * hosts, using it to compute key
+ */
+
+ md5_buffer(target->iScsiName, strlen(target->iScsiName), md5);
+
+ pool = virGetStoragePool(conn, name, md5, &esxStorageBackendISCSIDrv, NULL);
+
+ cleanup:
+
+ esxVI_HostInternetScsiHbaStaticTarget_Free(&target);
+
+ return pool;
+
+}
+
+
+
+static virStoragePoolPtr
+esxStorageBackendISCSIPoolLookupByUUID(virConnectPtr conn,
+ const unsigned char *uuid)
+{
+ virStoragePoolPtr pool = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+
+ if (esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to obtain iSCSI adapter"));
+ goto cleanup;
+ }
+
+ /* FIXME: code just looks for software iSCSI adapter */
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return NULL;
+ }
+
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ md5_buffer(target->iScsiName, strlen(target->iScsiName), md5);
+
+ if (memcmp(uuid, md5, VIR_UUID_STRING_BUFLEN) == 0) {
+ break;
+ }
+ }
+
+ if (target == NULL) {
+ /* pool not found, error handling done by the base driver */
+ goto cleanup;
+ }
+
+ pool = virGetStoragePool(conn,
+ target->iScsiName,
+ md5,
+ &esxStorageBackendISCSIDrv,
+ NULL);
+
+ cleanup:
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return pool;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIPoolRefresh(virStoragePoolPtr pool,
+ unsigned int flags)
+{
+ int result = -1;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_ManagedObjectReference *hostStorageSystem = NULL;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+
+ virCheckFlags(0, -1);
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "configManager.storageSystem\0") < 0 ||
+ esxVI_LookupHostSystemProperties(priv->primary,
+ propertyNameList, &hostSystem) < 0 ||
+ esxVI_GetManagedObjectReference(hostSystem,
+ "configManager.storageSystem", &hostStorageSystem,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ goto cleanup;
+ }
+
+ /**
+ * ESX does not allow rescan on a particular target,
+ * rescan all the static targets
+ */
+ if (esxVI_RescanHba(priv->primary, hostStorageSystem,
+ hostInternetScsiHba->device) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ManagedObjectReference_Free(&hostStorageSystem);
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return result;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIPoolGetInfo(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ virStoragePoolInfoPtr info)
+{
+ /* these fields are not valid for iSCSI pool */
+ info->allocation = info->capacity = info->available = 0;
+ info->state = VIR_STORAGE_POOL_RUNNING;
+
+ return 0;
+}
+
+
+
+static char *
+esxStorageBackendISCSIPoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
+{
+ char *xml = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ virStoragePoolDef def;
+
+ virCheckFlags(0, NULL);
+
+ memset(&def, 0, sizeof(def));
+
+ if (esxVI_LookupHostInternetScsiHba(priv->primary, &hostInternetScsiHba)) {
+ goto cleanup;
+ }
+
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ if (STREQ(target->iScsiName, pool->name)) {
+ break;
+ }
+ }
+
+ if (target == NULL) {
+ /* pool not found */
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find storage pool with name '%s'"), pool->name);
+ goto cleanup;
+ }
+
+ def.name = pool->name;
+ memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
+
+ def.type = VIR_STORAGE_POOL_ISCSI;
+
+ def.source.initiator.iqn = target->iScsiName;
+
+ def.source.nhost = 1;
+ if (VIR_ALLOC_N(def.source.hosts, def.source.nhost) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ def.source.hosts[0].name = target->address;
+ if (target->port) {
+ def.source.hosts[0].port = target->port->value;
+ }
+
+ /* TODO: add CHAP authentication params */
+
+ xml = virStoragePoolDefFormat(&def);
+
+ cleanup:
+
+ VIR_FREE(def.source.hosts);
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return xml;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIPoolNumberOfStorageVolumes(virStoragePoolPtr pool)
+{
+ int count = 0;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL;
+ const esxVI_HostScsiTopologyLun *hostScsiTopologyLun = NULL;
+ bool success = false;
+
+ if (esxVI_LookupHostScsiTopologyLunListByTargetName(
+ priv->primary, pool->name, &hostScsiTopologyLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (hostScsiTopologyLun = hostScsiTopologyLunList ;
+ hostScsiTopologyLun != NULL;
+ hostScsiTopologyLun = hostScsiTopologyLun->_next) {
+ ++count;
+ }
+
+ success = true;
+
+ cleanup:
+
+ esxVI_HostScsiTopologyLun_Free(&hostScsiTopologyLunList);
+
+ return success ? count : -1;
+
+}
+
+
+static int
+esxStorageBackendISCSIPoolListStorageVolumes(virStoragePoolPtr pool,
+ char **const names,
+ int maxnames)
+{
+ int count = 0;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL;
+ const esxVI_HostScsiTopologyLun *hostScsiTopologyLun = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ bool success = false;
+ int i = 0;
+
+ if (esxVI_LookupHostScsiTopologyLunListByTargetName(
+ priv->primary, pool->name, &hostScsiTopologyLunList) < 0) {
+ goto cleanup;
+ }
+
+ if (hostScsiTopologyLunList == NULL) {
+ /* iSCSI adapter may not be enabled on ESX host */
+ return 0;
+ }
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ /* O^2 but still faster than hash given N is not that large */
+ for (scsiLun = scsiLunList; scsiLun != NULL && count < maxnames;
+ scsiLun = scsiLun->_next) {
+ for (hostScsiTopologyLun = hostScsiTopologyLunList;
+ hostScsiTopologyLun != NULL && count < maxnames;
+ hostScsiTopologyLun = hostScsiTopologyLun->_next) {
+ if (STREQ(hostScsiTopologyLun->scsiLun, scsiLun->key)) {
+ names[count] = strdup(scsiLun->deviceName);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ ++count;
+ }
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+
+ esxVI_HostScsiTopologyLun_Free(&hostScsiTopologyLunList);
+ esxVI_ScsiLun_Free(&scsiLunList);
+
+ return count;
+}
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeLookupByName(virStoragePoolPtr pool,
+ const char *name)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+ if (STREQ(scsiLun->deviceName, name)) {
+ /**
+ * ScsiLun provides an UUID field that is unique accross
+ * multiple servers. But this field length is ~55 characters
+ * compute MD5 hash to transform it to an acceptable
+ * libvirt format
+ */
+ md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ /**
+ * ScsiLun provides displayName and canonicalName but both are
+ * optional and its observed that they can be NULL, using
+ * deviceName to create volume.
+ */
+ volume = virGetStorageVol(pool->conn, pool->name, name, uuid_string,
+ &esxStorageBackendISCSIDrv, NULL);
+ break;
+ }
+ }
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+
+ return volume;
+
+}
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeLookupByPath(virConnectPtr conn, const char *path)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *poolName = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ esxVI_ScsiLun *scsiLun = NULL;
+ const esxVI_HostScsiDisk *hostScsiDisk = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList ; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+ hostScsiDisk = esxVI_HostScsiDisk_DynamicCast(scsiLun);
+
+ if (hostScsiDisk != NULL &&
+ STREQ(hostScsiDisk->devicePath, path)) {
+ /* Found matching device */
+ if (esxVI_LookupStoragePoolNameByScsiLunKey(
+ priv->primary, hostScsiDisk->key, &poolName) < 0) {
+ goto cleanup;
+ }
+
+ md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ volume = virGetStorageVol(conn, poolName, path, uuid_string,
+ &esxStorageBackendISCSIDrv, NULL);
+ break;
+ }
+ }
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+ VIR_FREE(poolName);
+
+ return volume;
+
+}
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeLookupByKey(virConnectPtr conn, const char *key)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *poolName = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+
+ /* key may be LUN device path */
+ if (STRPREFIX(key, "/")) {
+ return esxStorageBackendISCSIVolumeLookupByPath(conn, key);
+ }
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+
+ memset(uuid_string, '\0', sizeof(uuid_string));
+ memset(md5, '\0', sizeof(md5));
+
+ md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ if (STREQ(key, uuid_string)) {
+ /* Found matching UUID */
+ if (esxVI_LookupStoragePoolNameByScsiLunKey(
+ priv->primary, scsiLun->key, &poolName) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(conn,
+ poolName,
+ scsiLun->deviceName,
+ uuid_string,
+ &esxStorageBackendISCSIDrv,
+ NULL);
+ break;
+ }
+ }
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+ VIR_FREE(poolName);
+
+ return volume;
+
+}
+
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeCreateXML(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ const char *xmldesc ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, NULL);
+
+ /* not supported operation for iSCSI pools */
+ return NULL;
+}
+
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeCreateXMLFrom(
+ virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ const char *xmldesc ATTRIBUTE_UNUSED,
+ virStorageVolPtr sourceVolume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, NULL);
+
+ /* not supported operation for iSCSI pools */
+ return NULL;
+}
+
+
+
+static char*
+esxStorageBackendISCSIVolumeGetXMLDesc(virStorageVolPtr volume,
+ unsigned int flags)
+{
+ char *xml = NULL;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ virStoragePoolDef pool;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ const esxVI_HostScsiDisk *hostScsiDisk = NULL;
+ virStorageVolDef def;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ virCheckFlags(0, NULL);
+
+ memset(&pool, 0, sizeof(pool));
+ memset(&def, 0, sizeof(def));
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+ hostScsiDisk =
+ esxVI_HostScsiDisk_DynamicCast((esxVI_ScsiLun *)scsiLun);
+
+ if (hostScsiDisk != NULL &&
+ STREQ(hostScsiDisk->deviceName, volume->name)) {
+ break;
+ }
+ }
+
+ if (hostScsiDisk == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could find volume with name: %s"), volume->name);
+ goto cleanup;
+ }
+
+ pool.type = VIR_STORAGE_POOL_ISCSI;
+
+ def.name = volume->name;
+
+ md5_buffer(scsiLun->uuid, strlen(hostScsiDisk->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ if (esxVI_String_DeepCopyValue(&def.key, uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ /* iSCSI LUN exposes a block device */
+ def.type = VIR_STORAGE_VOL_BLOCK;
+
+ def.target.path = hostScsiDisk->devicePath;
+
+ def.capacity = hostScsiDisk->capacity->block->value *
+ hostScsiDisk->capacity->blockSize->value;
+
+ def.allocation = def.capacity;
+
+ /* iSCSI LUN(s) hosting a datastore will be auto-mounted by
+ * ESX host
+ */
+ def.target.format = VIR_STORAGE_FILE_RAW;
+
+ xml = virStorageVolDefFormat(&pool, &def);
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+ VIR_FREE(def.key);
+
+ return xml;
+
+}
+
+static int
+esxStorageBackendISCSIVolumeDelete(virStorageVolPtr volume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ /* unsupported operation for iSCSI volume */
+ return 1;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIVolumeWipe(virStorageVolPtr volume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ /* unsupported operation for iSCSI volume */
+ return 1;
+
+}
+
+
+
+static char*
+esxStorageBackendISCSIVolumeGetPath(virStorageVolPtr volume)
+{
+ char *path;
+
+ if (virAsprintf(&path, "%s", volume->name) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return path;
+
+}
+
+
+
+virStorageDriver esxStorageBackendISCSIDrv = {
+ .name = "ESX ISCSI backend",
+ .open = NULL, /* 1.0.0 */
+ .close = NULL, /* 1.0.0 */
+ .numOfPools = esxStorageBackendISCSINumberOfStoragePools, /* 1.0.0 */
+ .listPools = esxStorageBackendISCSIListStoragePools, /* 1.0.0 */
+ .poolLookupByName = esxStorageBackendISCSIPoolLookupByName, /* 1.0.0 */
+ .poolLookupByUUID = esxStorageBackendISCSIPoolLookupByUUID, /* 1.0.0 */
+ .poolRefresh = esxStorageBackendISCSIPoolRefresh, /* 1.0.0 */
+ .poolGetInfo = esxStorageBackendISCSIPoolGetInfo, /* 1.0.0 */
+ .poolGetXMLDesc = esxStorageBackendISCSIPoolGetXMLDesc, /* 1.0.0 */
+ .poolNumOfVolumes = esxStorageBackendISCSIPoolNumberOfStorageVolumes, /* 1.0.0 */
+ .poolListVolumes = esxStorageBackendISCSIPoolListStorageVolumes, /* 1.0.0 */
+ .volLookupByName = esxStorageBackendISCSIVolumeLookupByName, /* 1.0.0 */
+ .volLookupByKey = esxStorageBackendISCSIVolumeLookupByKey, /* 1.0.0 */
+ .volLookupByPath = esxStorageBackendISCSIVolumeLookupByPath, /* 1.0.0 */
+ .volCreateXML = esxStorageBackendISCSIVolumeCreateXML, /* 1.0.0 */
+ .volCreateXMLFrom = esxStorageBackendISCSIVolumeCreateXMLFrom, /* 1.0.0 */
+ .volGetXMLDesc = esxStorageBackendISCSIVolumeGetXMLDesc, /* 1.0.0 */
+ .volDelete = esxStorageBackendISCSIVolumeDelete, /* 1.0.0 */
+ .volWipe = esxStorageBackendISCSIVolumeWipe, /* 1.0.0 */
+ .volGetPath = esxStorageBackendISCSIVolumeGetPath, /* 1.0.0 */
+};
diff --git a/src/esx/esx_storage_backend_iscsi.h b/src/esx/esx_storage_backend_iscsi.h
new file mode 100644
index 0000000..f78da46
--- /dev/null
+++ b/src/esx/esx_storage_backend_iscsi.h
@@ -0,0 +1,29 @@
+/*
+ * esx_storage_backend_iscsi.h: ESX storage backend for iSCSI handling
+ *
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __ESX_STORAGE_BACKEND_ISCSI_H__
+# define __ESX_STORAGE_BACKEND_ISCSI_H__
+
+# include "driver.h"
+
+extern virStorageDriver esxStorageBackendISCSIDrv;
+
+#endif /* __ESX_STORAGE_BACKEND_ISCSI_H__ */
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 5530ea7..6952c69 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -31,6 +31,7 @@
#include "esx_private.h"
#include "esx_storage_driver.h"
#include "esx_storage_backend_vmfs.h"
+#include "esx_storage_backend_iscsi.h"
#define VIR_FROM_THIS VIR_FROM_ESX
@@ -42,11 +43,13 @@
*/
enum {
VMFS = 0,
+ ISCSI,
LAST_DRIVER
};
static virStorageDriverPtr backendDrv[] = {
- &esxStorageBackendVMFSDrv
+ &esxStorageBackendVMFSDrv,
+ &esxStorageBackendISCSIDrv
};
static virDrvOpenStatus
@@ -465,9 +468,12 @@ esxStorageVolumeLookupByPath(virConnectPtr conn, const char *path)
* VMFS Datastore path follows cannonical format i.e.:
* [<datastore_name>] <file_path>
* WHEREAS
+ * iSCSI LUNs device path follows normal linux path convention
*/
if (STRPREFIX(path, "[")) {
volume = backendDrv[VMFS]->volLookupByPath(conn, path);
+ } else if (STRPREFIX(path, "/")) {
+ volume = backendDrv[ISCSI]->volLookupByPath(conn, path);
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected volume path format: %s"), path);
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 9fb2c11..12100d7 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -4875,5 +4875,337 @@ esxVI_LookupManagedObjectHelper(esxVI_Context *ctx,
}
+int
+esxVI_LookupHostInternetScsiHbaStaticTargetByName(
+ esxVI_Context *ctx,
+ const char *name,
+ esxVI_HostInternetScsiHbaStaticTarget **ret,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+
+ if (esxVI_LookupHostInternetScsiHba(ctx, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to obtain hostInternetScsiHba"));
+ goto cleanup;
+ }
+
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return 0;
+ }
+
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ if (STREQ(target->iScsiName, name)) {
+ break;
+ }
+ }
+
+ if (target == NULL) {
+ if (occurrence == esxVI_Occurrence_RequiredItem) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find storage pool with name: %s"), name);
+ }
+ goto cleanup;
+ }
+
+ if (esxVI_HostInternetScsiHbaStaticTarget_DeepCopy(
+ ret, (esxVI_HostInternetScsiHbaStaticTarget *)target) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return result;
+}
+
+
+int
+esxVI_LookupHostInternetScsiHba(
+ esxVI_Context *ctx,
+ esxVI_HostInternetScsiHba **hostInternetScsiHba)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_HostHostBusAdapter *hostHostBusAdapterList = NULL;
+ esxVI_HostHostBusAdapter *hostHostBusAdapter = NULL;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.hostBusAdapter\0") < 0 ||
+ esxVI_LookupHostSystemProperties(ctx, propertyNameList,
+ &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.hostBusAdapter")) {
+ if (esxVI_HostHostBusAdapter_CastListFromAnyType(
+ dynamicProperty->val, &hostHostBusAdapterList) < 0 ||
+ hostHostBusAdapterList == NULL) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ /* See vSphere API documentation about HostInternetScsiHba for details */
+ for (hostHostBusAdapter = hostHostBusAdapterList;
+ hostHostBusAdapter != NULL;
+ hostHostBusAdapter = hostHostBusAdapter->_next) {
+ esxVI_HostInternetScsiHba *candidate=
+ esxVI_HostInternetScsiHba_DynamicCast(hostHostBusAdapter);
+
+ if (candidate) {
+ if (esxVI_HostInternetScsiHba_DeepCopy(hostInternetScsiHba,
+ candidate) < 0) {
+ goto cleanup;
+ }
+ break;
+ }
+ }
+
+ result = 0;
+
+cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_HostHostBusAdapter_Free(&hostHostBusAdapterList);
+
+ return result;
+}
+
+
+int
+esxVI_LookupScsiLunList(esxVI_Context *ctx,
+ esxVI_ScsiLun **ret)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.scsiLun\0") < 0 ||
+ esxVI_LookupHostSystemProperties(
+ ctx, propertyNameList, &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.scsiLun")) {
+ if (esxVI_ScsiLun_CastListFromAnyType(dynamicProperty->val,
+ &scsiLunList) < 0) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ if (scsiLunList == NULL ||
+ esxVI_ScsiLun_DeepCopyList(ret, scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+
+ return result;
+
+}
+
+
+int
+esxVI_LookupHostScsiTopologyLunListByTargetName(
+ esxVI_Context *ctx, const char *name, esxVI_HostScsiTopologyLun **ret)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_HostScsiTopologyInterface *hostScsiInterfaceList = NULL;
+ const esxVI_HostScsiTopologyInterface *hostScsiInterface = NULL;
+ const esxVI_HostScsiTopologyTarget *hostScsiTopologyTarget = NULL;
+ bool found = false;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.scsiTopology.adapter\0") < 0 ||
+ esxVI_LookupHostSystemProperties(
+ ctx, propertyNameList, &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.scsiTopology.adapter")) {
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ if ((esxVI_HostScsiTopologyInterface_CastListFromAnyType
+ (dynamicProperty->val, &hostScsiInterfaceList) < 0)) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ if (hostScsiInterfaceList == NULL) {
+ /* iSCSI adapter may not be enabled */
+ return 0;
+ }
+
+ /* See vSphere API documentation about HostScsiTopologyInterface */
+ for (hostScsiInterface = hostScsiInterfaceList;
+ hostScsiInterface != NULL && !found;
+ hostScsiInterface = hostScsiInterface->_next) {
+ for (hostScsiTopologyTarget = hostScsiInterface->target;
+ hostScsiTopologyTarget != NULL;
+ hostScsiTopologyTarget = hostScsiTopologyTarget->_next) {
+ const esxVI_HostInternetScsiTargetTransport *candidate =
+ esxVI_HostInternetScsiTargetTransport_DynamicCast(
+ hostScsiTopologyTarget->transport);
+
+ if (candidate && STREQ(candidate->iScsiName, name)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found || hostScsiTopologyTarget == NULL) {
+ goto cleanup;
+ }
+
+ if (esxVI_HostScsiTopologyLun_DeepCopyList(
+ ret, hostScsiTopologyTarget->lun) < 0) {
+ goto cleanup;
+ }
+
+ if (*ret == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Target not found"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ return result;
+}
+
+
+int
+esxVI_LookupStoragePoolNameByScsiLunKey(esxVI_Context *ctx,
+ const char *key,
+ char **poolName)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_HostScsiTopologyInterface *hostScsiInterfaceList = NULL;
+ const esxVI_HostScsiTopologyInterface *hostScsiInterface = NULL;
+ const esxVI_HostScsiTopologyTarget *hostScsiTopologyTarget = NULL;
+ bool found = false;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.scsiTopology.adapter\0") < 0 ||
+ esxVI_LookupHostSystemProperties(
+ ctx, propertyNameList, &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.scsiTopology.adapter")) {
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ if ((esxVI_HostScsiTopologyInterface_CastListFromAnyType
+ (dynamicProperty->val, &hostScsiInterfaceList) < 0)) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ if (hostScsiInterfaceList == NULL) {
+ /* iSCSI adapter may not be enabled */
+ return 0;
+ }
+
+ /* See vSphere API documentation about HostScsiTopologyInterface */
+ for (hostScsiInterface = hostScsiInterfaceList;
+ hostScsiInterface != NULL && !found;
+ hostScsiInterface = hostScsiInterface->_next) {
+ for (hostScsiTopologyTarget = hostScsiInterface->target;
+ hostScsiTopologyTarget != NULL;
+ hostScsiTopologyTarget = hostScsiTopologyTarget->_next) {
+ const esxVI_HostInternetScsiTargetTransport *candidate =
+ esxVI_HostInternetScsiTargetTransport_DynamicCast(
+ hostScsiTopologyTarget->transport);
+
+ if (candidate) {
+ /* iterate hostScsiTopologyLun list to find matching key */
+ const esxVI_HostScsiTopologyLun *hostScsiTopologyLun =
+ hostScsiTopologyTarget->lun;
+ for (; hostScsiTopologyLun != NULL;
+ hostScsiTopologyLun = hostScsiTopologyLun->_next) {
+ if (STREQ(hostScsiTopologyLun->scsiLun, key)) {
+ *poolName = strdup(candidate->iScsiName);
+
+ if (*poolName == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ }
+ /* hostScsiTopologyLun iteration done, terminate loop */
+ break;
+ }
+ }
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ return result;
+}
+
+
#include "esx_vi.generated.c"
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d7895a0..8e56044 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -528,6 +528,24 @@ int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
int esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion);
+int esxVI_LookupHostInternetScsiHbaStaticTargetByName(esxVI_Context *ctx,
+ const char *name, esxVI_HostInternetScsiHbaStaticTarget **ret,
+ esxVI_Occurrence occurrence);
+
+int esxVI_LookupHostInternetScsiHba(
+ esxVI_Context *ctx,
+ esxVI_HostInternetScsiHba **hostInternetScsiHba);
+
+int esxVI_LookupScsiLunList(esxVI_Context *ctx, esxVI_ScsiLun **ret);
+
+int esxVI_LookupHostScsiTopologyLunListByTargetName(
+ esxVI_Context *ctx, const char *name, esxVI_HostScsiTopologyLun **ret);
+
+int
+esxVI_LookupStoragePoolNameByScsiLunKey(esxVI_Context *ctx,
+ const char *key,
+ char **poolName);
+
# include "esx_vi.generated.h"
#endif /* __ESX_VI_H__ */
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index c4a3e56..21f5b10 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -58,6 +58,14 @@ enum AutoStartWaitHeartbeatSetting
end
+enum FibreChannelPortType
+ fabric
+ loop
+ pointToPoint
+ unknown
+end
+
+
enum ManagedEntityStatus
gray
green
@@ -128,6 +136,12 @@ enum VirtualMachinePowerState
end
+enum vStorageSupport
+ vStorageUnknown
+end
+
+
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Objects
#
@@ -262,6 +276,13 @@ object HostAutoStartManagerConfig
AutoStartPowerInfo powerInfo ol
end
+object HostBlockAdapterTargetTransport extends HostTargetTransport
+end
+
+
+object HostBlockHba extends HostHostBusAdapter
+end
+
object HostConfigManager
ManagedObjectReference cpuScheduler o
@@ -309,6 +330,31 @@ object HostDatastoreBrowserSearchSpec
Boolean sortFoldersFirst o
end
+object HostDevice
+ String deviceName r
+ String deviceType r
+end
+
+
+object HostDiskDimensionsLba
+ Int blockSize r
+ Long block r
+end
+
+
+object HostFibreChannelHba extends HostHostBusAdapter
+ Long nodeWorldWideName r
+ FibreChannelPortType portType r
+ Long portWorldWideName r
+ Long speed r
+end
+
+
+object HostFibreChannelTargetTransport extends HostTargetTransport
+ Long nodeWorldWideName r
+ Long portWorldWideName r
+end
+
object HostFileSystemVolume
String type r
@@ -323,6 +369,164 @@ object HostIpConfig
String subnetMask o
end
+object HostHostBusAdapter
+ Int bus r
+ String device r
+ String driver o
+ String key o
+ String model r
+ String pci o
+ String status r
+end
+
+
+object HostInternetScsiTargetTransport extends HostTargetTransport
+ String iScsiName r
+ String iScsiAlias r
+ String address ol
+
+end
+
+
+object HostInternetScsiHba extends HostHostBusAdapter
+ HostInternetScsiHbaAuthenticationCapabilities authenticationCapabilities r
+ HostInternetScsiHbaAuthenticationProperties authenticationProperties r
+ HostInternetScsiHbaDiscoveryCapabilities discoveryCapabilities r
+ HostInternetScsiHbaDiscoveryProperties discoveryProperties r
+ HostInternetScsiHbaIPCapabilities ipCapabilities r
+ HostInternetScsiHbaIPProperties ipProperties r
+ String iScsiName r
+ Boolean isSoftwareBased r
+ HostInternetScsiHbaParamValue advancedOptions ol
+ HostInternetScsiHbaSendTarget configuredSendTarget ol
+ HostInternetScsiHbaStaticTarget configuredStaticTarget ol
+ Int currentSpeedMb o
+ HostInternetScsiHbaDigestCapabilities digestCapabilities o
+ HostInternetScsiHbaDigestProperties digestProperties o
+ String iScsiAlias o
+ Int maxSpeedMb o
+ OptionDef supportedAdvancedOptions ol
+end
+
+
+
+object HostInternetScsiHbaAuthenticationCapabilities
+ Boolean chapAuthSettable r
+ Boolean krb5AuthSettable r
+ Boolean spkmAuthSettable r
+ Boolean srpAuthSettable r
+ Boolean mutualChapSettable o
+ Boolean targetChapSettable o
+ Boolean targetMutualChapSettable o
+end
+
+
+object HostInternetScsiHbaAuthenticationProperties
+ Boolean chapAuthEnabled r
+ String chapAuthenticationType o
+ Boolean chapInherited o
+ String chapName o
+ String chapSecret o
+ String mutualChapAuthenticationType o
+ Boolean mutualChapInherited o
+ String mutualChapName o
+ String mutualChapSecret o
+end
+
+
+object HostInternetScsiHbaDigestCapabilities
+ Boolean dataDigestSettable o
+ Boolean headerDigestSettable o
+ Boolean targetDataDigestSettable o
+ Boolean targetHeaderDigestSettable o
+end
+
+
+object HostInternetScsiHbaDigestProperties
+ Boolean dataDigestInherited o
+ String dataDigestType o
+ Boolean headerDigestInherited o
+ String headerDigestType o
+end
+
+
+object HostInternetScsiHbaDiscoveryCapabilities
+ Boolean iSnsDiscoverySettable r
+ Boolean sendTargetsDiscoverySettable r
+ Boolean slpDiscoverySettable r
+ Boolean staticTargetDiscoverySettable r
+end
+
+
+object HostInternetScsiHbaDiscoveryProperties
+ Boolean iSnsDiscoveryEnabled r
+ Boolean sendTargetsDiscoveryEnabled r
+ Boolean slpDiscoveryEnabled r
+ Boolean staticTargetDiscoveryEnabled r
+ String iSnsDiscoveryMethod o
+ String iSnsHost o
+ String slpDiscoveryMethod o
+ String slpHost o
+end
+
+object HostInternetScsiHbaIPCapabilities
+ Boolean addressSettable r
+ Boolean alternateDnsServerAddressSettable r
+ Boolean defaultGatewaySettable r
+ Boolean ipConfigurationMethodSettable r
+ Boolean primaryDnsServerAddressSettable r
+ Boolean subnetMaskSettable r
+ Boolean arpRedirectSettable o
+ Boolean hostNameAsTargetAddress o
+ Boolean ipv6Supported o
+ Boolean mtuSettable o
+ Boolean nameAliasSettable o
+end
+
+
+object HostInternetScsiHbaIPProperties
+ Boolean dhcpConfigurationEnabled r
+ String address o
+ String alternateDnsServerAddress o
+ Boolean arpRedirectEnabled o
+ String defaultGateway o
+ String ipv6Address o
+ String ipv6DefaultGateway o
+ Boolean jumboFramesEnabled o
+ String mac o
+ Int mtu o
+ String primaryDnsServerAddress o
+ String subnetMask o
+end
+
+
+object HostInternetScsiHbaParamValue extends OptionValue
+ Boolean isInherited o
+end
+
+
+object HostInternetScsiHbaSendTarget
+ String address r
+ HostInternetScsiHbaParamValue advancedOptions ol
+ HostInternetScsiHbaAuthenticationProperties authenticationProperties o
+ HostInternetScsiHbaDigestProperties digestProperties o
+ String parent o
+ Int port o
+ OptionDef supportedAdvancedOptions ol
+end
+
+
+object HostInternetScsiHbaStaticTarget
+ String address r
+ String iScsiName r
+ HostInternetScsiHbaParamValue advancedOptions ol
+ HostInternetScsiHbaAuthenticationProperties authenticationProperties o
+ HostInternetScsiHbaDigestProperties digestProperties o
+ String parent o
+ Int port o
+ OptionDef supportedAdvancedOptions ol
+end
+
object HostMountInfo
String path o
@@ -418,12 +622,55 @@ object HostPortGroupSpec
HostNetworkPolicy policy r
end
+object HostParallelScsiHba extends HostHostBusAdapter
+end
+
+
+object HostParallelScsiTargetTransport extends HostTargetTransport
+end
+
+
+object HostScsiDisk extends ScsiLun
+ HostDiskDimensionsLba capacity r
+ String devicePath r
+end
+
object HostScsiDiskPartition
String diskName r
Int partition r
end
+object HostScsiTopology
+ HostScsiTopologyInterface adapater ol
+end
+
+
+object HostScsiTopologyInterface
+ String adapter r
+ String key r
+ HostScsiTopologyTarget target ol
+end
+
+
+object HostScsiTopologyLun
+ String key r
+ Int lun r
+ String scsiLun r
+end
+
+
+object HostScsiTopologyTarget
+ String key r
+ Int target r
+ HostScsiTopologyLun lun ol
+ HostTargetTransport transport o
+end
+
+
+object HostTargetTransport
+end
+
object HostVirtualSwitch
String name r
@@ -526,12 +773,22 @@ object ObjectUpdate
MissingProperty missingSet i
end
+object OptionDef extends ElementDescription
+ OptionType optionType r
+end
+
object OptionType
Boolean valueIsReadonly o
end
+object OptionValue
+ String key r
+ AnyType value r
+end
+
+
object PerfCounterInfo
Int key r
ElementDescription nameInfo r
@@ -664,6 +921,45 @@ object SelectionSpec
end
+object ScsiLun extends HostDevice
+ String lunType r
+ String operationalState rl
+ String uuid r
+ ScsiLunDurableName alternateName ol
+ String canonicalName o
+ ScsiLunCapabilities capabilities o
+ ScsiLunDescriptor descriptor ol
+ String displayName o
+ ScsiLunDurableName durableName o
+ String key o
+ String model o
+ Int queueDepth o
+ String revision o
+ Int scsiLevel o
+ String serialNumber o
+ Byte standardInquiry ol
+ String vendor o
+end
+
+
+object ScsiLunCapabilities
+ Boolean updateDisplayNameSupported r
+end
+
+
+object ScsiLunDescriptor
+ String id r
+ String quality r
+end
+
+
+object ScsiLunDurableName
+ String namespace r
+ Byte namespaceId r
+ Byte data ol
+end
+
+
object ServiceContent
ManagedObjectReference rootFolder r
ManagedObjectReference propertyCollector r
@@ -1138,6 +1434,12 @@ method RemoveVirtualSwitch
end
+method RescanHba
+ ManagedObjectReference _this r
+ String hbaDevice r
+end
+
+
method RetrieveProperties returns ObjectContent ol
ManagedObjectReference _this:propertyCollector r
PropertyFilterSpec specSet rl
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 2883ac0..af4e7e8 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -1532,6 +1532,21 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN
Object.FEATURE__ANY_TYPE,
"HostDatastoreBrowserSearchResults" : Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
+ "HostHostBusAdapter" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
+ "HostInternetScsiHba" : Object.FEATURE__DYNAMIC_CAST |
+ Object.FEATURE__DEEP_COPY,
+ "HostInternetScsiTargetTransport" : Object.FEATURE__DYNAMIC_CAST,
+ "HostScsiDisk" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__DYNAMIC_CAST,
+ "HostScsiTopologyInterface" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
+ "HostScsiTopologyLun" : Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__LIST |
+ Object.FEATURE__DEEP_COPY,
+ "HostScsiTopologyTarget" : Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__LIST,
"HostPortGroup" : Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
"HostVirtualSwitch" : Object.FEATURE__DEEP_COPY |
@@ -1543,6 +1558,10 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN
Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
"ResourcePoolResourceUsage" : Object.FEATURE__ANY_TYPE,
+ "ScsiLun" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__DEEP_COPY,
+ "ScsiLunDurableName" : Object.FEATURE__LIST,
"ServiceContent" : Object.FEATURE__DESERIALIZE,
"SharesInfo" : Object.FEATURE__ANY_TYPE,
"TaskInfo" : Object.FEATURE__LIST |
--
1.7.9.5
12 years
[libvirt] [PATCH] conf: fix virDomainNetGetActualDirect*() and BridgeName()
by Laine Stump
This resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=881480
These three functions:
virDomainNetGetActualBridgeName
virDomainNetGetActualDirectDev
virDomainNetGetActualDirectMode
return attributes that are in a union whose contents are interpreted
differently depending on the actual->type and so they should only
return non-0 when actual->type is 'bridge' (in the first case) or
'direct' (in the other two cases, but I had neglected to do that, so
...DirectDev() was returning bridge.brname (which happens to share the
same spot in the union with direct.linkdev) if actual->type was
'bridge', and ...BridgeName was returning direct.linkdev when
actual->type was 'direct'.
How does this involve Bug 881480 (which was about the inability to
switch between two networks that both have "<forward mode='bridge'/>
<bridge name='xxx'/>"? Whenever the return value of
virDomainNetGetActualDirectDev() for the new and old network
definitions doesn't match, qemuDomainChangeNet() requires a "complete
reconnect" of the device, which qemu currently doesn't
support. ...DirectDev() *should* have been returning NULL for old and
new, but was instead returning the old and new bridge names, which
differ.
(The other two functions weren't causing any behavioral problems in
virDomainChangeNet(), but their problem and fix was identical, so I
included them in this same patch).
were supposed to only return non-0 values when
---
src/conf/domain_conf.c | 33 ++++++++++++++++++---------------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 814859a..4ffb39d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -15130,11 +15130,12 @@ virDomainNetGetActualBridgeName(virDomainNetDefPtr iface)
{
if (iface->type == VIR_DOMAIN_NET_TYPE_BRIDGE)
return iface->data.bridge.brname;
- if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
- return NULL;
- if (!iface->data.network.actual)
- return NULL;
- return iface->data.network.actual->data.bridge.brname;
+ if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+ iface->data.network.actual &&
+ iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ return iface->data.network.actual->data.bridge.brname;
+ }
+ return NULL;
}
const char *
@@ -15142,11 +15143,12 @@ virDomainNetGetActualDirectDev(virDomainNetDefPtr iface)
{
if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
return iface->data.direct.linkdev;
- if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
- return NULL;
- if (!iface->data.network.actual)
- return NULL;
- return iface->data.network.actual->data.direct.linkdev;
+ if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+ iface->data.network.actual &&
+ iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ return iface->data.network.actual->data.direct.linkdev;
+ }
+ return NULL;
}
int
@@ -15154,11 +15156,12 @@ virDomainNetGetActualDirectMode(virDomainNetDefPtr iface)
{
if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
return iface->data.direct.mode;
- if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
- return 0;
- if (!iface->data.network.actual)
- return 0;
- return iface->data.network.actual->data.direct.mode;
+ if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+ iface->data.network.actual &&
+ iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ return iface->data.network.actual->data.direct.mode;
+ }
+ return 0;
}
virDomainHostdevDefPtr
--
1.7.11.7
12 years
[libvirt] [PATCHv2 0/2] qemu: support live update of an interface's filter
by Laine Stump
These two patches enable making a live change to the nwfilter of a
guest's interface via virDomainUpdateDeviceFlags (virsh
update-device).
Differences from V1:
1) add patch from Stefan Berger to do a proper comparison of the
values stored in the filterparams hashtable.
2) simplify virNWFilterHashTableEqual to use Stefan's new function, and
remove a couple of pointless comparisons based on Stefan's review.
12 years
[libvirt] [PATCH] virsh: Report errors if arguments of the schedinfo command are incorrect
by Peter Krempa
Libvirt's helper API's when called directly don't raise the error so
that virsh remembers it. Subsequent calls to libvirt API's might reset
the error.
In case of schedinfo virDomainFree() in the cleanup section resets the
error when virTypedParameterAssignFromStr() fails.
This patch adds function vshSaveLibvirtError() that can be called after
calling libvirt helper APIs to ensure the error is remembered.
---
tools/virsh-domain.c | 8 ++++++--
tools/virsh.c | 9 +++++++++
tools/virsh.h | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 73ebba9..1f7aff7 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -3512,8 +3512,10 @@ cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd,
if (virTypedParameterAssign(&(params[nparams++]),
param->field,
param->type,
- val) < 0)
+ val) < 0) {
+ vshSaveLibvirtError();
goto cleanup;
+ }
continue;
}
@@ -3523,8 +3525,10 @@ cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd,
if (virTypedParameterAssignFromStr(&(params[nparams++]),
param->field,
param->type,
- set_val) < 0)
+ set_val) < 0) {
+ vshSaveLibvirtError();
goto cleanup;
+ }
continue;
}
diff --git a/tools/virsh.c b/tools/virsh.c
index dea3f82..322f778 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -240,6 +240,15 @@ virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error)
virDefaultErrorFunc(error);
}
+/* Store a libvirt error that is from a helper API that doesn't raise errors
+ * so it doesn't get overwritten */
+void
+vshSaveLibvirtError(void)
+{
+ virFreeError(last_error);
+ last_error = virSaveLastError();
+}
+
/*
* Reset libvirt error on graceful fallback paths
*/
diff --git a/tools/virsh.h b/tools/virsh.h
index ba44f42..6913ed1 100644
--- a/tools/virsh.h
+++ b/tools/virsh.h
@@ -346,6 +346,7 @@ struct _vshCtrlData {
extern virErrorPtr last_error;
void vshReportError(vshControl *ctl);
void vshResetLibvirtError(void);
+void vshSaveLibvirtError(void);
/* allocation wrappers */
void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
--
1.8.0
12 years
[libvirt] [PATCH] maint: Misc whitespace cleanups
by Peter Krempa
---
src/conf/storage_conf.c | 2 +-
src/util/virtypedparam.c | 6 ++----
tools/virsh-domain.c | 3 +--
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 3fdc5b6..2d72d06 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -441,7 +441,7 @@ virStoragePoolDefParseAuthChap(xmlXPathContextPtr ctxt,
static int
virStoragePoolDefParseAuthCephx(xmlXPathContextPtr ctxt,
- virStoragePoolAuthCephxPtr auth) {
+ virStoragePoolAuthCephxPtr auth) {
char *uuid = NULL;
auth->username = virXPathString("string(./auth/@username)", ctxt);
if (auth->username == NULL) {
diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c
index 0b7a268..7f0a44b 100644
--- a/src/util/virtypedparam.c
+++ b/src/util/virtypedparam.c
@@ -250,11 +250,9 @@ virTypedParameterAssignFromStr(virTypedParameterPtr param, const char *name,
}
break;
case VIR_TYPED_PARAM_BOOLEAN:
- if (STRCASEEQ(val, "true") ||
- STREQ(val, "1")) {
+ if (STRCASEEQ(val, "true") || STREQ(val, "1")) {
param->value.b = true;
- } else if (STRCASEEQ(val, "false") ||
- STREQ(val, "0")) {
+ } else if (STRCASEEQ(val, "false") || STREQ(val, "0")) {
param->value.b = false;
} else {
virReportError(VIR_ERR_INVALID_ARG,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index f12777c..73ebba9 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -3576,8 +3576,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
/* Print SchedulerType */
schedulertype = virDomainGetSchedulerType(dom, &nparams);
if (schedulertype != NULL) {
- vshPrint(ctl, "%-15s: %s\n", _("Scheduler"),
- schedulertype);
+ vshPrint(ctl, "%-15s: %s\n", _("Scheduler"), schedulertype);
VIR_FREE(schedulertype);
} else {
vshPrint(ctl, "%-15s: %s\n", _("Scheduler"), _("Unknown"));
--
1.8.0
12 years
[libvirt] [PATCH 0/?] Various issues found by coverity
by Ján Tomko
Ján Tomko (7):
nwfilter: fix NULL pointer check in virNWFilterSnoopReqNew
conf: prevent crash with no uuid in cephx auth secret
cgroup: fix impossible overrun in virCgroupAddTaskController
libssh2_session: support DSS keys as well
virsh: fix error messages in iface-bridge
conf: check the return value of virXPathNodeSet
conf: snapshot: check return value of virDomainSnapshotObjListNum
src/conf/domain_conf.c | 8 ++++++--
src/conf/snapshot_conf.c | 2 +-
src/conf/storage_conf.c | 12 ++++++------
src/nwfilter/nwfilter_dhcpsnoop.c | 4 ++--
src/rpc/virnetsshsession.c | 1 +
src/util/cgroup.c | 2 +-
tools/virsh-interface.c | 4 ++--
7 files changed, 19 insertions(+), 14 deletions(-)
--
1.7.8.6
12 years
[libvirt] [PATCHv2 0/3] IPv6 enhancements; put dnsmasq parameters in conf-file
by Gene Czarcinski
Rebased 30 Nov 2012
These three patch files are packaged together because they serially
depend on each other. These files have been rebased to "v3" of
the dnsmasq capabilities and bind-dynamic patches.
The DHCPv6 support checks dnsmasq's version and requires a minimum of 2.64.
Also, using dnsmasq for providing the RA service is checked against the
dnsmasq version and is currently 2.64.
As with IPv4, IPv6 DHCP is only one subnetwork on an interface. Additionally,
if other IPv6 addresses are defined, a warning message is issued since
the Router Advertisement service will support only state-full (DHCP) or
state-less (SLAAC) addressing on a network interface (not both). Thus, the
additional subnetworks will need to be manually configured to properly function.
If dnsmasq provides the RA service, it also points to itself as a RDNSS
(Recursive DNS Server) as part of the information is supplies.
If IPv6 DHCP is not being run, then SLAAC addressing is supported for
any IPv6 addresses specified.
Gene Czarcinski (3):
v1: allow guest to guest IPv6 without gateway definition
v8.1 add support for DHCPv6
v7.9: put dnsmasq parameters into conf-file
docs/formatnetwork.html.in | 126 ++++-
docs/schemas/network.rng | 12 +-
src/conf/network_conf.c | 100 ++--
src/network/bridge_driver.c | 590 ++++++++++++++-------
src/network/bridge_driver.h | 7 +-
src/util/dnsmasq.c | 9 +-
tests/networkxml2argvdata/dhcp6-nat-network.argv | 14 +
tests/networkxml2argvdata/dhcp6-nat-network.xml | 24 +
tests/networkxml2argvdata/dhcp6-network.argv | 14 +
tests/networkxml2argvdata/dhcp6-network.xml | 14 +
.../dhcp6host-routed-network.argv | 12 +
.../dhcp6host-routed-network.xml | 19 +
tests/networkxml2argvdata/isolated-network.argv | 25 +-
.../networkxml2argvdata/nat-network-dns-hosts.argv | 14 +-
.../nat-network-dns-srv-record-minimal.argv | 34 +-
.../nat-network-dns-srv-record.argv | 24 +-
.../nat-network-dns-txt-record.argv | 22 +-
tests/networkxml2argvdata/nat-network.argv | 22 +-
tests/networkxml2argvdata/netboot-network.argv | 28 +-
.../networkxml2argvdata/netboot-proxy-network.argv | 26 +-
tests/networkxml2argvdata/routed-network.argv | 11 +-
tests/networkxml2argvtest.c | 47 +-
22 files changed, 838 insertions(+), 356 deletions(-)
create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.argv
create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.xml
create mode 100644 tests/networkxml2argvdata/dhcp6-network.argv
create mode 100644 tests/networkxml2argvdata/dhcp6-network.xml
create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.argv
create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.xml
--
1.7.11.7
12 years
[libvirt] [PATCH] Fix the coding style
by Osier Yang
Fix the "if ... else" coding style, and indentions problem.
---
src/libvirt.c | 107 ++++++++++++++++++++++++++++++--------------------------
1 files changed, 57 insertions(+), 50 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index f509cc7..1304853 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1199,18 +1199,19 @@ do_open(const char *name,
goto failed;
}
- VIR_DEBUG("trying driver %d (%s) ...",
- i, virDriverTab[i]->name);
+ VIR_DEBUG("trying driver %d (%s) ...", i, virDriverTab[i]->name);
res = virDriverTab[i]->open(ret, auth, flags);
VIR_DEBUG("driver %d %s returned %s",
- i, virDriverTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) goto failed;
- else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virDriverTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->driver = virDriverTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ goto failed;
}
}
@@ -1225,30 +1226,32 @@ do_open(const char *name,
for (i = 0; i < virNetworkDriverTabCount; i++) {
res = virNetworkDriverTab[i]->open(ret, auth, flags);
VIR_DEBUG("network driver %d %s returned %s",
- i, virNetworkDriverTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) {
- break;
- } else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virNetworkDriverTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->networkDriver = virNetworkDriverTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ break;
}
}
for (i = 0; i < virInterfaceDriverTabCount; i++) {
res = virInterfaceDriverTab[i]->open(ret, auth, flags);
VIR_DEBUG("interface driver %d %s returned %s",
- i, virInterfaceDriverTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) {
- break;
- } else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virInterfaceDriverTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->interfaceDriver = virInterfaceDriverTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ break;
}
}
@@ -1256,15 +1259,16 @@ do_open(const char *name,
for (i = 0; i < virStorageDriverTabCount; i++) {
res = virStorageDriverTab[i]->open(ret, auth, flags);
VIR_DEBUG("storage driver %d %s returned %s",
- i, virStorageDriverTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) {
- break;
- } else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virStorageDriverTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->storageDriver = virStorageDriverTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ break;
}
}
@@ -1272,15 +1276,16 @@ do_open(const char *name,
for (i = 0; i < virDeviceMonitorTabCount; i++) {
res = virDeviceMonitorTab[i]->open(ret, auth, flags);
VIR_DEBUG("node driver %d %s returned %s",
- i, virDeviceMonitorTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) {
- break;
- } else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virDeviceMonitorTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->deviceMonitor = virDeviceMonitorTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ break;
}
}
@@ -1288,15 +1293,16 @@ do_open(const char *name,
for (i = 0; i < virSecretDriverTabCount; i++) {
res = virSecretDriverTab[i]->open(ret, auth, flags);
VIR_DEBUG("secret driver %d %s returned %s",
- i, virSecretDriverTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) {
- break;
- } else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virSecretDriverTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->secretDriver = virSecretDriverTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ break;
}
}
@@ -1304,15 +1310,16 @@ do_open(const char *name,
for (i = 0; i < virNWFilterDriverTabCount; i++) {
res = virNWFilterDriverTab[i]->open(ret, auth, flags);
VIR_DEBUG("nwfilter driver %d %s returned %s",
- i, virNWFilterDriverTab[i]->name,
- res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
- (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
- (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
- if (res == VIR_DRV_OPEN_ERROR) {
- break;
- } else if (res == VIR_DRV_OPEN_SUCCESS) {
+ i, virNWFilterDriverTab[i]->name,
+ res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
+ (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
+ (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
+
+ if (res == VIR_DRV_OPEN_SUCCESS) {
ret->nwfilterDriver = virNWFilterDriverTab[i];
break;
+ } else if (res == VIR_DRV_OPEN_ERROR) {
+ break;
}
}
--
1.7.7.6
12 years
[libvirt] [PATCH] virsh: don't crash if shutdown --mode not provided
by Eric Blake
virStringSplit requires a non-NULL input, but commit cef78ed forgot
to follow the rule.
* tools/virsh-domain.c (cmdReboot, cmdShutdown): Avoid NULL deref.
---
Pushing under the build-breaker rule.
tools/virsh-domain.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 9f1a3d4..f12777c 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -4036,20 +4036,20 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd)
const char *mode = NULL;
int flags = 0;
int rv;
- char **modes, **tmp;
+ char **modes = NULL, **tmp;
if (vshCommandOptString(cmd, "mode", &mode) < 0) {
vshError(ctl, "%s", _("Invalid type"));
return false;
}
- if (!(modes = virStringSplit(mode, ",", 0))) {
+ if (mode && !(modes = virStringSplit(mode, ",", 0))) {
vshError(ctl, "%s", _("Cannot parse mode string"));
return false;
}
tmp = modes;
- while (*tmp) {
+ while (tmp && *tmp) {
mode = *tmp;
if (STREQ(mode, "acpi")) {
flags |= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
@@ -4112,20 +4112,20 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd)
const char *name;
const char *mode = NULL;
int flags = 0;
- char **modes, **tmp;
+ char **modes = NULL, **tmp;
if (vshCommandOptString(cmd, "mode", &mode) < 0) {
vshError(ctl, "%s", _("Invalid type"));
return false;
}
- if (!(modes = virStringSplit(mode, ",", 0))) {
+ if (mode && !(modes = virStringSplit(mode, ",", 0))) {
vshError(ctl, "%s", _("Cannot parse mode string"));
return false;
}
tmp = modes;
- while (*tmp) {
+ while (tmp && *tmp) {
mode = *tmp;
if (STREQ(mode, "acpi")) {
flags |= VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
--
1.7.1
12 years
[libvirt] [PATCH] Fix indentions
by Osier Yang
---
Pushed under trival rule.
---
src/rpc/virnetmessage.c | 8 ++++----
src/util/event_poll.h | 12 ++++++------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/rpc/virnetmessage.c b/src/rpc/virnetmessage.c
index ce5f9d8..39300fa 100644
--- a/src/rpc/virnetmessage.c
+++ b/src/rpc/virnetmessage.c
@@ -271,8 +271,8 @@ int virNetMessageEncodeNumFDs(virNetMessagePtr msg)
if (numFDs > VIR_NET_MESSAGE_NUM_FDS_MAX) {
virReportError(VIR_ERR_RPC,
- _("Too many FDs to send %d, expected %d maximum"),
- numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
+ _("Too many FDs to send %d, expected %d maximum"),
+ numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
goto cleanup;
}
@@ -309,8 +309,8 @@ int virNetMessageDecodeNumFDs(virNetMessagePtr msg)
if (numFDs > VIR_NET_MESSAGE_NUM_FDS_MAX) {
virReportError(VIR_ERR_RPC,
- _("Received too many FDs %d, expected %d maximum"),
- numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
+ _("Received too many FDs %d, expected %d maximum"),
+ numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
goto cleanup;
}
diff --git a/src/util/event_poll.h b/src/util/event_poll.h
index c77b5df..64b2e96 100644
--- a/src/util/event_poll.h
+++ b/src/util/event_poll.h
@@ -37,9 +37,9 @@
* returns -1 if the file handle cannot be registered, 0 upon success
*/
int virEventPollAddHandle(int fd, int events,
- virEventHandleCallback cb,
- void *opaque,
- virFreeCallback ff);
+ virEventHandleCallback cb,
+ void *opaque,
+ virFreeCallback ff);
/**
* virEventPollUpdateHandle: change event set for a monitored file handle
@@ -74,9 +74,9 @@ int virEventPollRemoveHandle(int watch);
* integer timer id upon success
*/
int virEventPollAddTimeout(int frequency,
- virEventTimeoutCallback cb,
- void *opaque,
- virFreeCallback ff);
+ virEventTimeoutCallback cb,
+ void *opaque,
+ virFreeCallback ff);
/**
* virEventPollUpdateTimeout: change frequency for a timer
--
1.7.7.6
12 years