提交 60f0f55e 编写于 作者: A Ata E Husain Bohra 提交者: Matthias Bolte

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.
上级 258fb278
......@@ -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
......
......@@ -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 \
......
......@@ -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,
......
此差异已折叠。
/*
* esx_storage_backend_iscsi.h: ESX storage backend for iSCSI handling
*
* Copyright (C) 2012 Ata E Husain Bohra <ata.husain@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 esxStorageBackendISCSI;
#endif /* __ESX_STORAGE_BACKEND_ISCSI_H__ */
......@@ -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.:
* [<datastore_name>] <file_path>
* 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);
......
......@@ -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)) { \
......
......@@ -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"
......
此差异已折叠。
......@@ -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 |
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册