2012/11/10 Ata E Husain Bohra <ata.husain(a)hotmail.com>:
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
--- /dev/null
+++ b/src/esx/esx_storage_backend_iscsi.c
+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 */
This comment is wrong here, because a hash wouldn't help here. In
order to get the storage volume list this 2-dimensional list need to
be iterated. There is no way to do this faster, except adding a cache
but then you get the problem of ehen to invalidate it. So this 2 level
for loop is totally fine and the comment should be removed, because it
is misleading.
+ 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 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 ||
No need to look up the hostStorageSystem here. It is already available
here: ctx->hostSystem->configManager->storageSystem
+ 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 virStorageVolPtr
+esxStorageBackendISCSIVolumeCreateXML(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ const char *xmldesc ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, NULL);
A VIR_ERR_NO_SUPPORT error should be reported here.
+ /* 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);
A VIR_ERR_NO_SUPPORT error should be reported here.
+ /* not supported operation for iSCSI pools */
+ return NULL;
+}
+static int
+esxStorageBackendISCSIVolumeDelete(virStorageVolPtr volume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
A VIR_ERR_NO_SUPPORT error should be reported here.
+ /* unsupported operation for iSCSI volume */
+ return 1;
Should return -1;
+}
+
+
+
+static int
+esxStorageBackendISCSIVolumeWipe(virStorageVolPtr volume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
A VIR_ERR_NO_SUPPORT error should be reported here.
+ /* unsupported operation for iSCSI volume */
+ return 1;
Should return -1;
+}
+
+
+
+static char*
+esxStorageBackendISCSIVolumeGetPath(virStorageVolPtr volume)
+{
+ char *path;
+
+ if (virAsprintf(&path, "%s", volume->name) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
Can be simplified to strdup.
+ return 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
+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);
Needs to free propertyNameList and hostSystem too.
+ return result;
+
+}
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
@@ -128,6 +136,12 @@ enum VirtualMachinePowerState
end
+enum vStorageSupport
+ vStorageUnknown
+end
This enum is not used anywhere and can be removed.
ACK. No major problems left. I fixed the minor things I mentioned,
made make syntax-check pass and pushed the result. Thanks!
--
Matthias Bolte
http://photron.blogspot.com