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