From 60f0f55ee4686fecbffc5fb32f90863427d02a14 Mon Sep 17 00:00:00 2001 From: Ata E Husain Bohra Date: Fri, 9 Nov 2012 23:18:08 -0800 Subject: [PATCH] Add iSCSI backend storage driver for ESX 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. --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/esx/esx_driver.c | 2 +- src/esx/esx_storage_backend_iscsi.c | 774 ++++++++++++++++++++++++++++ src/esx/esx_storage_backend_iscsi.h | 30 ++ src/esx/esx_storage_driver.c | 9 +- src/esx/esx_vi.c | 340 +++++++++++- src/esx/esx_vi.h | 20 +- src/esx/esx_vi_generator.input | 351 +++++++++++++ src/esx/esx_vi_generator.py | 19 + 10 files changed, 1543 insertions(+), 4 deletions(-) create mode 100644 src/esx/esx_storage_backend_iscsi.c create mode 100644 src/esx/esx_storage_backend_iscsi.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 77bc04b937..586aa2b5cd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -32,6 +32,7 @@ src/datatypes.c src/driver.c src/esx/esx_driver.c src/esx/esx_network_driver.c +src/esx/esx_storage_backend_iscsi.c src/esx/esx_storage_backend_vmfs.c src/esx/esx_storage_driver.c src/esx/esx_util.c diff --git a/src/Makefile.am b/src/Makefile.am index b5c20c82ed..01cb9954c3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -498,6 +498,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_driver.c b/src/esx/esx_driver.c index 0374a98f13..a858298947 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4792,7 +4792,7 @@ esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags) } if (esxVI_RevertToSnapshot_Task(priv->primary, snapshotTree->snapshot, NULL, - &task) < 0 || + esxVI_Boolean_Undefined, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, snapshot->domain->uuid, esxVI_Occurrence_RequiredItem, priv->parsedUri->autoAnswer, &taskInfoState, diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c new file mode 100644 index 0000000000..b6cde96e8d --- /dev/null +++ b/src/esx/esx_storage_backend_iscsi.c @@ -0,0 +1,774 @@ + +/* + * esx_storage_backend_iscsi.c: ESX storage backend for iSCSI handling + * + * Copyright (C) 2012 Ata E Husain Bohra + * + * 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 + * . + * + */ + +#include + +#include +#include +#include + +#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_ESX + +/* + * 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 +esxStorageBackendISCSINumberOfPools(virConnectPtr conn) +{ + bool success = false; + int count = 0; + esxPrivate *priv = conn->storagePrivateData; + esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL; + esxVI_HostInternetScsiHbaStaticTarget *target; + + if (esxVI_LookupHostInternetScsiHba(priv->primary, + &hostInternetScsiHba) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("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 +esxStorageBackendISCSIListPools(virConnectPtr conn, char **const names, + const int maxnames) +{ + bool success = false; + int count = 0; + esxPrivate *priv = conn->storagePrivateData; + esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL; + esxVI_HostInternetScsiHbaStaticTarget *target; + int i; + + if (maxnames == 0) { + return 0; + } + + if (esxVI_LookupHostInternetScsiHba(priv->primary, + &hostInternetScsiHba) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("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) { + names[count] = strdup(target->iScsiName); + + if (names[count] == NULL) { + virReportOOMError(); + goto cleanup; + } + + ++count; + } + + success = true; + + cleanup: + if (! success) { + for (i = 0; i < count; ++i) { + VIR_FREE(names[i]); + } + } + + 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) { + goto cleanup; + } + + if (target == NULL) { + /* pool not found, error handling done by the base driver */ + 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, &esxStorageBackendISCSI, 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; + esxVI_HostInternetScsiHbaStaticTarget *target; + /* 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, "%s", + _("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, + &esxStorageBackendISCSI, 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_HostInternetScsiHba *hostInternetScsiHba = NULL; + + virCheckFlags(0, -1); + + if (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, + priv->primary->hostSystem->configManager->storageSystem, + hostInternetScsiHba->device) < 0) { + goto cleanup; + } + + result = 0; + + cleanup: + 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; + esxVI_HostInternetScsiHbaStaticTarget *target; + 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 != NULL) { + 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 +esxStorageBackendISCSIPoolNumberOfVolumes(virStoragePoolPtr pool) +{ + int count = 0; + esxPrivate *priv = pool->conn->storagePrivateData; + esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL; + esxVI_HostScsiTopologyLun *hostScsiTopologyLun; + + if (esxVI_LookupHostScsiTopologyLunListByTargetName + (priv->primary, pool->name, &hostScsiTopologyLunList) < 0) { + return -1; + } + + for (hostScsiTopologyLun = hostScsiTopologyLunList; + hostScsiTopologyLun != NULL; + hostScsiTopologyLun = hostScsiTopologyLun->_next) { + ++count; + } + + esxVI_HostScsiTopologyLun_Free(&hostScsiTopologyLunList); + + return count; +} + + + +static int +esxStorageBackendISCSIPoolListVolumes(virStoragePoolPtr pool, char **const names, + int maxnames) +{ + bool success = false; + int count = 0; + esxPrivate *priv = pool->conn->storagePrivateData; + esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL; + esxVI_HostScsiTopologyLun *hostScsiTopologyLun; + esxVI_ScsiLun *scsiLunList = NULL; + esxVI_ScsiLun *scsiLun = NULL; + int i; + + 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; + } + + 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; + esxVI_ScsiLun *scsiLun; + /* 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, + &esxStorageBackendISCSI, NULL); + break; + } + } + + cleanup: + esxVI_ScsiLun_Free(&scsiLunList); + + return volume; +} + + + +static virStorageVolPtr +esxStorageBackendISCSIVolumeLookupByPath(virConnectPtr conn, const char *path) +{ + virStorageVolPtr volume = NULL; + esxPrivate *priv = conn->storagePrivateData; + esxVI_ScsiLun *scsiLunList = NULL; + esxVI_ScsiLun *scsiLun; + esxVI_HostScsiDisk *hostScsiDisk = NULL; + char *poolName = 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 */ + VIR_FREE(poolName); + + 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, + &esxStorageBackendISCSI, 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; + esxVI_ScsiLun *scsiLun; + /* 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 */ + VIR_FREE(poolName); + + if (esxVI_LookupStoragePoolNameByScsiLunKey(priv->primary, + scsiLun->key, + &poolName) < 0) { + goto cleanup; + } + + volume = virGetStorageVol(conn, poolName, scsiLun->deviceName, + uuid_string, &esxStorageBackendISCSI, + 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); + + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("iSCSI storage pool does not support volume creation")); + + return NULL; +} + + + +static virStorageVolPtr +esxStorageBackendISCSIVolumeCreateXMLFrom(virStoragePoolPtr pool ATTRIBUTE_UNUSED, + const char *xmldesc ATTRIBUTE_UNUSED, + virStorageVolPtr sourceVolume ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virCheckFlags(0, NULL); + + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("iSCSI storage pool does not support volume creation")); + + return NULL; +} + + + +static char * +esxStorageBackendISCSIVolumeGetXMLDesc(virStorageVolPtr volume, + unsigned int flags) +{ + char *xml = NULL; + esxPrivate *priv = volume->conn->storagePrivateData; + virStoragePoolDef pool; + esxVI_ScsiLun *scsiLunList = NULL; + esxVI_ScsiLun *scsiLun; + 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(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); + + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("iSCSI storage pool does not support volume deletion")); + + return -1; +} + + + +static int +esxStorageBackendISCSIVolumeWipe(virStorageVolPtr volume ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virCheckFlags(0, -1); + + + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("iSCSI storage pool does not support volume wiping")); + + return -1; +} + + + +static char * +esxStorageBackendISCSIVolumeGetPath(virStorageVolPtr volume) +{ + char *path = strdup(volume->name); + + if (path == NULL) { + virReportOOMError(); + return NULL; + } + + return path; +} + + + +virStorageDriver esxStorageBackendISCSI = { + .numOfPools = esxStorageBackendISCSINumberOfPools, /* 1.0.1 */ + .listPools = esxStorageBackendISCSIListPools, /* 1.0.1 */ + .poolLookupByName = esxStorageBackendISCSIPoolLookupByName, /* 1.0.1 */ + .poolLookupByUUID = esxStorageBackendISCSIPoolLookupByUUID, /* 1.0.1 */ + .poolRefresh = esxStorageBackendISCSIPoolRefresh, /* 1.0.1 */ + .poolGetInfo = esxStorageBackendISCSIPoolGetInfo, /* 1.0.1 */ + .poolGetXMLDesc = esxStorageBackendISCSIPoolGetXMLDesc, /* 1.0.1 */ + .poolNumOfVolumes = esxStorageBackendISCSIPoolNumberOfVolumes, /* 1.0.1 */ + .poolListVolumes = esxStorageBackendISCSIPoolListVolumes, /* 1.0.1 */ + .volLookupByName = esxStorageBackendISCSIVolumeLookupByName, /* 1.0.1 */ + .volLookupByPath = esxStorageBackendISCSIVolumeLookupByPath, /* 1.0.1 */ + .volLookupByKey = esxStorageBackendISCSIVolumeLookupByKey, /* 1.0.1 */ + .volCreateXML = esxStorageBackendISCSIVolumeCreateXML, /* 1.0.1 */ + .volCreateXMLFrom = esxStorageBackendISCSIVolumeCreateXMLFrom, /* 1.0.1 */ + .volGetXMLDesc = esxStorageBackendISCSIVolumeGetXMLDesc, /* 1.0.1 */ + .volDelete = esxStorageBackendISCSIVolumeDelete, /* 1.0.1 */ + .volWipe = esxStorageBackendISCSIVolumeWipe, /* 1.0.1 */ + .volGetPath = esxStorageBackendISCSIVolumeGetPath, /* 1.0.1 */ +}; diff --git a/src/esx/esx_storage_backend_iscsi.h b/src/esx/esx_storage_backend_iscsi.h new file mode 100644 index 0000000000..00c9e2940e --- /dev/null +++ b/src/esx/esx_storage_backend_iscsi.h @@ -0,0 +1,30 @@ + +/* + * esx_storage_backend_iscsi.h: ESX storage backend for iSCSI handling + * + * Copyright (C) 2012 Ata E Husain Bohra + * + * 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 + * . + * + */ + +#ifndef __ESX_STORAGE_BACKEND_ISCSI_H__ +# define __ESX_STORAGE_BACKEND_ISCSI_H__ + +# include "driver.h" + +extern virStorageDriver esxStorageBackendISCSI; + +#endif /* __ESX_STORAGE_BACKEND_ISCSI_H__ */ diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c index 52f46b4c22..e6c09aae68 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_BACKEND }; static virStorageDriverPtr backends[] = { - &esxStorageBackendVMFS + &esxStorageBackendVMFS, + &esxStorageBackendISCSI }; @@ -386,9 +389,13 @@ esxStorageVolumeLookupByPath(virConnectPtr conn, const char *path) * * VMFS Datastore path follows cannonical format i.e.: * [] + * WHEREAS + * iSCSI LUNs device path follows normal linux path convention */ if (STRPREFIX(path, "[")) { return backends[VMFS]->volLookupByPath(conn, path); + } else if (STRPREFIX(path, "/")) { + return backends[ISCSI]->volLookupByPath(conn, path); } else { virReportError(VIR_ERR_INVALID_ARG, _("Unexpected volume path format: %s"), path); diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 9fb2c11daf..564b35cfd6 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -2780,7 +2780,8 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid, virUUIDFormat(uuid, uuid_string); if (esxVI_FindByUuid(ctx, ctx->datacenter->_reference, uuid_string, - esxVI_Boolean_True, &managedObjectReference) < 0) { + esxVI_Boolean_True, esxVI_Boolean_Undefined, + &managedObjectReference) < 0) { return -1; } @@ -4673,6 +4674,343 @@ esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersio +int +esxVI_LookupHostInternetScsiHbaStaticTargetByName + (esxVI_Context *ctx, const char *name, + esxVI_HostInternetScsiHbaStaticTarget **target, esxVI_Occurrence occurrence) +{ + int result = -1; + esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL; + esxVI_HostInternetScsiHbaStaticTarget *candidate = 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 (candidate = hostInternetScsiHba->configuredStaticTarget; + candidate != NULL; candidate = candidate->_next) { + if (STREQ(candidate->iScsiName, name)) { + break; + } + } + + if (candidate == NULL) { + if (occurrence == esxVI_Occurrence_RequiredItem) { + virReportError(VIR_ERR_NO_STORAGE_POOL, + _("Could not find storage pool with name: %s"), name); + } + + goto cleanup; + } + + if (esxVI_HostInternetScsiHbaStaticTarget_DeepCopy(target, candidate) < 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 || + 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 **scsiLunList) +{ + int result = -1; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *hostSystem = NULL; + esxVI_DynamicProperty *dynamicProperty; + + if (esxVI_String_AppendValueToList(&propertyNameList, + "config.storageDevice.scsiLun") < 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; + } + + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + + result = 0; + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&hostSystem); + + return result; +} + + + +int +esxVI_LookupHostScsiTopologyLunListByTargetName + (esxVI_Context *ctx, const char *name, + esxVI_HostScsiTopologyLun **hostScsiTopologyLunList) +{ + int result = -1; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_ObjectContent *hostSystem = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_HostScsiTopologyInterface *hostScsiInterfaceList = NULL; + esxVI_HostScsiTopologyInterface *hostScsiInterface = NULL; + esxVI_HostScsiTopologyTarget *hostScsiTopologyTarget = NULL; + bool found = false; + esxVI_HostInternetScsiTargetTransport *candidate = NULL; + + if (hostScsiTopologyLunList == NULL || *hostScsiTopologyLunList != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_String_AppendValueToList + (&propertyNameList, + "config.storageDevice.scsiTopology.adapter") < 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; + } + + break; + } 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) { + candidate = esxVI_HostInternetScsiTargetTransport_DynamicCast + (hostScsiTopologyTarget->transport); + + if (candidate != NULL && STREQ(candidate->iScsiName, name)) { + found = true; + break; + } + } + } + + if (!found || hostScsiTopologyTarget == NULL) { + goto cleanup; + } + + if (hostScsiTopologyTarget->lun == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Target not found")); + goto cleanup; + } + + if (esxVI_HostScsiTopologyLun_DeepCopyList(hostScsiTopologyLunList, + hostScsiTopologyTarget->lun) < 0) { + 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; + esxVI_HostScsiTopologyInterface *hostScsiInterface = NULL; + esxVI_HostScsiTopologyTarget *hostScsiTopologyTarget = NULL; + esxVI_HostInternetScsiTargetTransport *candidate; + esxVI_HostScsiTopologyLun *hostScsiTopologyLun; + bool found = false; + + if (poolName == NULL || *poolName != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_String_AppendValueToList + (&propertyNameList, + "config.storageDevice.scsiTopology.adapter") < 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; + } + + break; + } 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) { + candidate = esxVI_HostInternetScsiTargetTransport_DynamicCast + (hostScsiTopologyTarget->transport); + + if (candidate != NULL) { + /* iterate hostScsiTopologyLun list to find matching key */ + for (hostScsiTopologyLun = hostScsiTopologyTarget->lun; + 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; +} + + #define ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE_IGNORE(_name) \ if (STREQ(dynamicProperty->name, #_name)) { \ diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index d7895a0013..a121d1caa0 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -526,7 +526,25 @@ int esxVI_WaitForTaskCompletion(esxVI_Context *ctx, int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo, esxVI_HostCpuIdInfo *hostCpuIdInfo); -int esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion); +int esxVI_ProductVersionToDefaultVirtualHWVersion + (esxVI_ProductVersion productVersion); + +int esxVI_LookupHostInternetScsiHbaStaticTargetByName + (esxVI_Context *ctx, const char *name, + esxVI_HostInternetScsiHbaStaticTarget **target, + esxVI_Occurrence occurrence); + +int esxVI_LookupHostInternetScsiHba + (esxVI_Context *ctx, esxVI_HostInternetScsiHba **hostInternetScsiHba); + +int esxVI_LookupScsiLunList(esxVI_Context *ctx, esxVI_ScsiLun **scsiLunList); + +int esxVI_LookupHostScsiTopologyLunListByTargetName + (esxVI_Context *ctx, const char *name, + esxVI_HostScsiTopologyLun **hostScsiTopologyLunList); + +int esxVI_LookupStoragePoolNameByScsiLunKey(esxVI_Context *ctx, const char *key, + char **poolName); # include "esx_vi.generated.h" diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index c4a3e56998..22c114e0aa 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 @@ -144,6 +152,9 @@ object AboutInfo String productLineId r String apiType r String apiVersion r + String instanceUuid o + String licenseProductName o + String licenseProductVersion o end @@ -184,6 +195,7 @@ object DatastoreInfo String url r Long freeSpace r Long maxFileSize r + DateTime timestamp o end @@ -218,6 +230,12 @@ object EventArgument end +object ExtendedElementDescription extends ElementDescription + String messageCatalogKeyPrefix r + KeyAnyValue messageArg ol +end + + object FileBackedVirtualDiskSpec extends VirtualDiskSpec Long capacityKb r end @@ -227,6 +245,7 @@ object FileInfo String path r Long fileSize o DateTime modification o + String owner o end @@ -238,6 +257,7 @@ object FileQueryFlags Boolean fileType r Boolean fileSize r Boolean modification r + Boolean fileOwner o end @@ -263,6 +283,14 @@ object HostAutoStartManagerConfig end +object HostBlockAdapterTargetTransport extends HostTargetTransport +end + + +object HostBlockHba extends HostHostBusAdapter +end + + object HostConfigManager ManagedObjectReference cpuScheduler o ManagedObjectReference datastoreSystem o @@ -270,6 +298,7 @@ object HostConfigManager ManagedObjectReference storageSystem o ManagedObjectReference networkSystem o ManagedObjectReference vmotionSystem o + ManagedObjectReference virtualNicManager o ManagedObjectReference serviceSystem o ManagedObjectReference firewallSystem o ManagedObjectReference advancedOption o @@ -281,6 +310,9 @@ object HostConfigManager ManagedObjectReference bootDeviceSystem o ManagedObjectReference firmwareSystem o ManagedObjectReference healthStatusSystem o + ManagedObjectReference pciPassthruSystem o + ManagedObjectReference licenseManager o + ManagedObjectReference kernelModuleSystem o end @@ -310,6 +342,32 @@ object HostDatastoreBrowserSearchSpec end +object HostDevice + String deviceName r + String deviceType r +end + + +object HostDiskDimensionsLba + Int blockSize r + Long block r +end + + +object HostFibreChannelHba extends HostHostBusAdapter + Long portWorldWideName r + Long nodeWorldWideName r + FibreChannelPortType portType r + Long speed r +end + + +object HostFibreChannelTargetTransport extends HostTargetTransport + Long portWorldWideName r + Long nodeWorldWideName r +end + + object HostFileSystemVolume String type r String name r @@ -317,10 +375,169 @@ object HostFileSystemVolume end +object HostHostBusAdapter + String key o + String device r + Int bus r + String status r + String model r + String driver o + String pci o +end + + +object HostInternetScsiHba extends HostHostBusAdapter + Boolean isSoftwareBased r + HostInternetScsiHbaDiscoveryCapabilities discoveryCapabilities r + HostInternetScsiHbaDiscoveryProperties discoveryProperties r + HostInternetScsiHbaAuthenticationCapabilities authenticationCapabilities r + HostInternetScsiHbaAuthenticationProperties authenticationProperties r + HostInternetScsiHbaDigestCapabilities digestCapabilities o + HostInternetScsiHbaDigestProperties digestProperties o + HostInternetScsiHbaIPCapabilities ipCapabilities r + HostInternetScsiHbaIPProperties ipProperties r + OptionDef supportedAdvancedOptions i + HostInternetScsiHbaParamValue advancedOptions ol + String iScsiName r + String iScsiAlias o + HostInternetScsiHbaSendTarget configuredSendTarget ol + HostInternetScsiHbaStaticTarget configuredStaticTarget ol + Int maxSpeedMb o + Int currentSpeedMb o +end + + +object HostInternetScsiHbaAuthenticationCapabilities + Boolean chapAuthSettable r + Boolean krb5AuthSettable r + Boolean srpAuthSettable r + Boolean spkmAuthSettable r + Boolean mutualChapSettable o + Boolean targetChapSettable o + Boolean targetMutualChapSettable o +end + + +object HostInternetScsiHbaAuthenticationProperties + Boolean chapAuthEnabled r + String chapName o + String chapSecret o + String chapAuthenticationType o + Boolean chapInherited o + String mutualChapName o + String mutualChapSecret o + String mutualChapAuthenticationType o + Boolean mutualChapInherited o +end + + +object HostInternetScsiHbaDigestCapabilities + Boolean headerDigestSettable o + Boolean dataDigestSettable o + Boolean targetHeaderDigestSettable o + Boolean targetDataDigestSettable o +end + + +object HostInternetScsiHbaDigestProperties + String headerDigestType o + Boolean headerDigestInherited o + String dataDigestType o + Boolean dataDigestInherited o +end + + +object HostInternetScsiHbaDiscoveryCapabilities + Boolean iSnsDiscoverySettable r + Boolean slpDiscoverySettable r + Boolean staticTargetDiscoverySettable r + Boolean sendTargetsDiscoverySettable r +end + + +object HostInternetScsiHbaDiscoveryProperties + Boolean iSnsDiscoveryEnabled r + String iSnsDiscoveryMethod o + String iSnsHost o + Boolean slpDiscoveryEnabled r + String slpDiscoveryMethod o + String slpHost o + Boolean staticTargetDiscoveryEnabled r + Boolean sendTargetsDiscoveryEnabled r +end + + +object HostInternetScsiHbaIPCapabilities + Boolean addressSettable r + Boolean ipConfigurationMethodSettable r + Boolean subnetMaskSettable r + Boolean defaultGatewaySettable r + Boolean primaryDnsServerAddressSettable r + Boolean alternateDnsServerAddressSettable r + Boolean ipv6Supported o + Boolean arpRedirectSettable o + Boolean mtuSettable o + Boolean hostNameAsTargetAddress o +end + + +object HostInternetScsiHbaIPProperties + String mac o + String address o + Boolean dhcpConfigurationEnabled r + String subnetMask o + String defaultGateway o + String primaryDnsServerAddress o + String alternateDnsServerAddress o + String ipv6Address o + String ipv6SubnetMask o + String ipv6DefaultGateway o + Boolean arpRedirectEnabled o + Int mtu o + Boolean jumboFramesEnabled o +end + + +object HostInternetScsiHbaParamValue extends OptionValue + Boolean isInherited o +end + + +object HostInternetScsiHbaSendTarget + String address r + Int port o + HostInternetScsiHbaAuthenticationProperties authenticationProperties o + HostInternetScsiHbaDigestProperties digestProperties o + OptionDef supportedAdvancedOptions i + HostInternetScsiHbaParamValue advancedOptions ol + String parent o +end + + +object HostInternetScsiHbaStaticTarget + String address r + Int port o + String iScsiName r + HostInternetScsiHbaAuthenticationProperties authenticationProperties o + HostInternetScsiHbaDigestProperties digestProperties o + OptionDef supportedAdvancedOptions i + HostInternetScsiHbaParamValue advancedOptions ol + String parent o +end + + +object HostInternetScsiTargetTransport extends HostTargetTransport + String iScsiName r + String iScsiAlias r + String address ol +end + + object HostIpConfig Boolean dhcp r String ipAddress o String subnetMask o + HostIpConfigIpV6AddressConfiguration ipV6Config i end @@ -395,6 +612,14 @@ object HostNicTeamingPolicy end +object HostParallelScsiHba extends HostHostBusAdapter +end + + +object HostParallelScsiTargetTransport extends HostTargetTransport +end + + object HostPortGroup String key o HostPortGroupPort port ol @@ -419,12 +644,44 @@ object HostPortGroupSpec end +object HostScsiDisk extends ScsiLun + HostDiskDimensionsLba capacity r + String devicePath r +end + + object HostScsiDiskPartition String diskName r Int partition r end +object HostScsiTopologyInterface + String key r + String adapter 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 String key r @@ -450,6 +707,7 @@ end object HostVirtualSwitchBondBridge extends HostVirtualSwitchBridge String nicDevice rl HostVirtualSwitchBeaconConfig beacon o + LinkDiscoveryProtocolConfig linkDiscoveryProtocolConfig i end @@ -478,6 +736,7 @@ object HostVmfsVolume extends HostFileSystemVolume String uuid r HostScsiDiskPartition extent rl Boolean vmfsUpgradable r + HostForceMountedInfo forceMountedInfo i end @@ -489,6 +748,12 @@ object IsoImageFileQuery extends FileQuery end +object KeyAnyValue + String key r + AnyType value r +end + + object LocalDatastoreInfo extends DatastoreInfo String path o end @@ -532,6 +797,12 @@ object OptionType end +object OptionValue + String key r + AnyType value o +end + + object PerfCounterInfo Int key r ElementDescription nameInfo r @@ -659,6 +930,45 @@ object ResourcePoolResourceUsage end +object ScsiLun extends HostDevice + String key o + String uuid r + ScsiLunDescriptor descriptor ol + String canonicalName o + String displayName o + String lunType r + String vendor o + String model o + String revision o + Int scsiLevel o + String serialNumber o + ScsiLunDurableName durableName o + ScsiLunDurableName alternateName ol + Byte standardInquiry ol + Int queueDepth o + String operationalState rl + ScsiLunCapabilities capabilities o +end + + +object ScsiLunCapabilities + Boolean updateDisplayNameSupported r +end + + +object ScsiLunDescriptor + String quality r + String id r +end + + +object ScsiLunDurableName + String namespace r + Byte namespaceId r + Byte data ol +end + + object SelectionSpec String name o end @@ -688,6 +998,16 @@ object ServiceContent ManagedObjectReference fileManager o ManagedObjectReference virtualDiskManager o ManagedObjectReference virtualizationManager o + ManagedObjectReference snmpSystem o + ManagedObjectReference vmProvisioningChecker o + ManagedObjectReference vmCompatibilityChecker o + ManagedObjectReference ovfManager o + ManagedObjectReference ipPoolManager o + ManagedObjectReference dvSwitchManager o + ManagedObjectReference hostProfileManager o + ManagedObjectReference clusterProfileManager o + ManagedObjectReference complianceManager o + ManagedObjectReference localizationManager o end @@ -700,6 +1020,7 @@ end object TaskInfo String key r ManagedObjectReference task r + LocalizableMessage description i String name o String descriptionId r ManagedObjectReference entity o @@ -716,6 +1037,9 @@ object TaskInfo DateTime startTime o DateTime completeTime o Int eventChainId r + String changeTag o + String parentTaskKey o + String rootTaskKey o end @@ -763,9 +1087,14 @@ object VirtualMachineConfigSpec String name o String version o String uuid o + String instanceUuid o Long npivNodeWorldWideName ol Long npivPortWorldWideName ol String npivWorldWideNameType o + Short npivDesiredNodeWwns i + Short npivDesiredPortWwns i + Boolean npivTemporaryDisabled o + Boolean npivOnNonRdmDisks o String npivWorldWideNameOp o String locationId o String guestId o @@ -778,6 +1107,9 @@ object VirtualMachineConfigSpec VirtualMachineDefaultPowerOpInfo powerOpInfo i Int numCPUs o Long memoryMB o + Boolean memoryHotAddEnabled o + Boolean cpuHotAddEnabled o + Boolean cpuHotRemoveEnabled o VirtualDeviceConfigSpec deviceChange i ResourceAllocationInfo cpuAllocation o ResourceAllocationInfo memoryAllocation o @@ -788,6 +1120,11 @@ object VirtualMachineConfigSpec OptionValue extraConfig i String swapPlacement o VirtualMachineBootOptions bootOptions i + VmConfigSpec vAppConfig i + FaultToleranceConfigInfo ftInfo i + Boolean vAppConfigRemoved o + Boolean vAssertsEnabled o + Boolean changeTrackingEnabled o end @@ -804,10 +1141,13 @@ object VirtualMachineSnapshotTree ManagedObjectReference vm r String name r String description r + Int id o DateTime createTime r VirtualMachinePowerState state r Boolean quiesced r + String backupManifest o VirtualMachineSnapshotTree childSnapshotList ol + Boolean replaySupported o end @@ -838,6 +1178,7 @@ object VmDiskFileInfo extends FileInfo Int hardwareVersion o String controllerType o String diskExtents ol + Boolean thin o end @@ -851,6 +1192,7 @@ object VmDiskFileQueryFilter String diskType ol Int matchHardwareVersion ol String controllerType ol + Boolean thin o end @@ -860,6 +1202,7 @@ object VmDiskFileQueryFlags Boolean hardwareVersion r Boolean controllerType o Boolean diskExtents o + Boolean thin o end @@ -1016,6 +1359,7 @@ method FindByUuid returns ManagedObjectReference o ManagedObjectReference datacenter o String uuid r Boolean vmSearch r + Boolean instanceUuid o end @@ -1138,6 +1482,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 @@ -1147,6 +1497,7 @@ end method RevertToSnapshot_Task returns ManagedObjectReference r ManagedObjectReference _this r ManagedObjectReference host o + Boolean suppressPowerOn o end diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 2883ac0d97..af4e7e8abe 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 | -- GitLab