---
src/esx/esx_driver.c | 3 +-
src/esx/esx_storage_driver.c | 215 +++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vi.c | 57 +++++++-----
src/esx/esx_vi.h | 1 +
src/esx/esx_vi_generator.input | 32 ++++++
src/esx/esx_vi_generator.py | 7 +-
src/esx/esx_vi_methods.c | 12 +++
7 files changed, 296 insertions(+), 31 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index eda3fc2..f8d4771 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -353,7 +353,8 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
return 0;
}
- if (esxVI_LookupFileInfoByDatastorePath(data->ctx, def->src, &fileInfo,
+ if (esxVI_LookupFileInfoByDatastorePath(data->ctx, def->src,
+ false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index d2d8f22..3b959c2 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -709,7 +709,7 @@ esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char
*name)
}
if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
- &fileInfo,
+ false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
@@ -743,7 +743,8 @@ esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char
*keyOrPath)
goto cleanup;
}
- if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath, &fileInfo,
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath,
+ false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
@@ -761,6 +762,210 @@ esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char
*keyOrPath)
+static virStorageVolPtr
+esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc,
+ unsigned int flags)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_DatastoreInfo *datastoreInfo = NULL;
+ virStoragePoolDef poolDef;
+ virStorageVolDefPtr def = NULL;
+ char *tmp1;
+ char *tmp2;
+ char *datastorePath = NULL;
+ char *directoryName = NULL;
+ char *datastorePathWithoutFileName = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_FileBackedVirtualDiskSpec *virtualDiskSpec = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+
+ virCheckFlags(0, NULL);
+
+ memset(&poolDef, 0, sizeof (poolDef));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ /* Lookup storage pool type */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0
||
+ esxVI_LookupDatastoreByName(priv->primary, pool->name,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "info")) {
+ if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
+ &datastoreInfo) < 0) {
+ goto cleanup;
+ }
+
+ break;
+ }
+ }
+
+ if (esxVI_LocalDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ poolDef.type = VIR_STORAGE_POOL_DIR;
+ } else if (esxVI_NasDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ poolDef.type = VIR_STORAGE_POOL_NETFS;
+ } else if (esxVI_VmfsDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ poolDef.type = VIR_STORAGE_POOL_FS;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("DatastoreInfo has unexpected type"));
+ goto cleanup;
+ }
+
+ /* Parse config */
+ def = virStorageVolDefParseString(&poolDef, xmldesc);
+
+ if (def == NULL) {
+ goto cleanup;
+ }
+
+ if (def->type != VIR_STORAGE_VOL_FILE) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Creating non-file volumes is not supported"));
+ goto cleanup;
+ }
+
+ /* Validate config */
+ tmp1 = strchr(def->name, '/');
+ tmp2 = strrchr(def->name, '/');
+
+ if (tmp1 == NULL || tmp1 == def->name ||
+ tmp2 == NULL || tmp2[1] == '\0') {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Volume name '%s' doesn't have expected format
"
+ "'<directory>/<file>'"),
def->name);
+ goto cleanup;
+ }
+
+ if (! virFileHasSuffix(def->name, ".vmdk")) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Volume name '%s' has unsupported suffix, expecting
'.vmdk'"),
+ def->name);
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", pool->name, def->name)
< 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (def->target.format == VIR_STORAGE_FILE_VMDK) {
+ /* Create directory, if it doesn't exist yet */
+ if (esxUtil_ParseDatastorePath(datastorePath, NULL, &directoryName,
+ NULL) < 0) {
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s",
pool->name,
+ directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath
+ (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (fileInfo == NULL) {
+ if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
+ priv->primary->datacenter->_reference,
+ esxVI_Boolean_True) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Create VirtualDisk */
+ if (esxVI_FileBackedVirtualDiskSpec_Alloc(&virtualDiskSpec) < 0 ||
+ esxVI_Long_Alloc(&virtualDiskSpec->capacityKb) < 0) {
+ goto cleanup;
+ }
+
+ /* From the vSphere API documentation about VirtualDiskType ... */
+ if (def->allocation == def->capacity) {
+ /*
+ * "A preallocated disk has all space allocated at creation time
+ * and the space is zeroed on demand as the space is used."
+ */
+ virtualDiskSpec->diskType = (char *)"preallocated";
+ } else if (def->allocation == 0) {
+ /*
+ * "Space required for thin-provisioned virtual disk is allocated
+ * and zeroed on demand as the space is used."
+ */
+ virtualDiskSpec->diskType = (char *)"thin";
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unsupported capacity-to-allocation relation"));
+ goto cleanup;
+ }
+
+ /*
+ * FIXME: The adapter type is a required parameter, but there is no
+ * way to let the user specifiy it in the volume XML config. Therefore,
+ * default to 'busLogic' here.
+ */
+ virtualDiskSpec->adapterType = (char *)"busLogic";
+
+ virtualDiskSpec->capacityKb->value = def->capacity / 1024; /* Scale from
byte to kilobyte */
+
+ if (esxVI_CreateVirtualDisk_Task
+ (priv->primary, datastorePath,
priv->primary->datacenter->_reference,
+ esxVI_VirtualDiskSpec_DynamicCast(virtualDiskSpec), &task) < 0 ||
+ esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
+ esxVI_Occurrence_None,
+ priv->autoAnswer, &taskInfoState) < 0)
{
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create
volume"));
+ goto cleanup;
+ }
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Creation of %s volumes is not supported"),
+ virStorageFileFormatTypeToString(def->target.format));
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(pool->conn, pool->name, def->name,
datastorePath);
+
+ cleanup:
+ if (virtualDiskSpec != NULL) {
+ virtualDiskSpec->diskType = NULL;
+ virtualDiskSpec->adapterType = NULL;
+ }
+
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreInfo_Free(&datastoreInfo);
+ virStorageVolDefFree(def);
+ VIR_FREE(datastorePath);
+ VIR_FREE(directoryName);
+ VIR_FREE(datastorePathWithoutFileName);
+ esxVI_FileInfo_Free(&fileInfo);
+ esxVI_FileBackedVirtualDiskSpec_Free(&virtualDiskSpec);
+ esxVI_ManagedObjectReference_Free(&task);
+
+ return volume;
+}
+
+
+
static int
esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
{
@@ -782,7 +987,7 @@ esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr
info)
}
if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
- &fileInfo,
+ false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
@@ -875,7 +1080,7 @@ esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int flags)
}
if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
- &fileInfo,
+ false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
@@ -986,7 +1191,7 @@ static virStorageDriver esxStorageDriver = {
esxStorageVolumeLookupByName, /* volLookupByName */
esxStorageVolumeLookupByKeyOrPath, /* volLookupByKey */
esxStorageVolumeLookupByKeyOrPath, /* volLookupByPath */
- NULL, /* volCreateXML */
+ esxStorageVolumeCreateXML, /* volCreateXML */
NULL, /* volCreateXMLFrom */
NULL, /* volDelete */
NULL, /* volWipe */
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index a6950fd..8d83eac 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -2940,6 +2940,7 @@ esxVI_LookupCurrentSnapshotTree
int
esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
const char *datastorePath,
+ bool lookupFolder,
esxVI_FileInfo **fileInfo,
esxVI_Occurrence occurrence)
{
@@ -2954,6 +2955,7 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
esxVI_ObjectContent *datastore = NULL;
esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
+ esxVI_FolderFileQuery *folderFileQuery = NULL;
esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
esxVI_IsoImageFileQuery *isoImageFileQuery = NULL;
esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL;
@@ -3030,32 +3032,41 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
searchSpec->details->fileSize = esxVI_Boolean_True;
searchSpec->details->modification = esxVI_Boolean_False;
- if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
- esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
- esxVI_FileQuery_AppendToList
- (&searchSpec->query,
- esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
- goto cleanup;
- }
+ if (lookupFolder) {
+ if (esxVI_FolderFileQuery_Alloc(&folderFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(folderFileQuery)) < 0) {
+ goto cleanup;
+ }
+ } else {
+ if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
+ esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
+ goto cleanup;
+ }
- vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
- vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True;
- vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
- vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
- vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
+ vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
+ vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True;
+ vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
+ vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
+ vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
- if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 ||
- esxVI_FileQuery_AppendToList
- (&searchSpec->query,
- esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) {
- goto cleanup;
- }
+ if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) {
+ goto cleanup;
+ }
- if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 ||
- esxVI_FileQuery_AppendToList
- (&searchSpec->query,
- esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) {
- goto cleanup;
+ if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) {
+ goto cleanup;
+ }
}
if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 3d1aee0..773a1c6 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -401,6 +401,7 @@ int esxVI_LookupCurrentSnapshotTree
int esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
const char *datastorePath,
+ bool lookupFolder,
esxVI_FileInfo **fileInfo,
esxVI_Occurrence occurrence);
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 0fb9448..b911c22 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -166,6 +166,11 @@ object Description
end
+object DeviceBackedVirtualDiskSpec extends VirtualDiskSpec
+ String device r
+end
+
+
object DynamicProperty
String name r
AnyType val r
@@ -190,6 +195,11 @@ object Event
end
+object FileBackedVirtualDiskSpec extends VirtualDiskSpec
+ Long capacityKb r
+end
+
+
object FileInfo
String path r
Long fileSize o
@@ -528,6 +538,12 @@ object UserSession
end
+object VirtualDiskSpec
+ String diskType r
+ String adapterType r
+end
+
+
object VirtualMachineConfigSpec
String changeVersion o
String name o
@@ -694,6 +710,14 @@ method CreateSnapshot_Task returns ManagedObjectReference r
end
+method CreateVirtualDisk_Task returns ManagedObjectReference r
+ ManagedObjectReference _this:VirtualDiskManager r
+ String name r
+ ManagedObjectReference datacenter o
+ VirtualDiskSpec spec r
+end
+
+
method DestroyPropertyFilter
ManagedObjectReference _this r
end
@@ -728,6 +752,14 @@ method Logout
end
+method MakeDirectory
+ ManagedObjectReference _this:FileManager r
+ String name r
+ ManagedObjectReference datacenter o
+ Boolean createParentDirectories o
+end
+
+
method MigrateVM_Task returns ManagedObjectReference r
ManagedObjectReference _this r
ManagedObjectReference pool o
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 411fd80..be96a03 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -45,10 +45,12 @@ valid_occurrences = [OCCURRENCE__REQUIRED_ITEM,
class Parameter:
- autobind_map = { "PerformanceManager" : "perfManager",
+ autobind_map = { "FileManager" : "fileManager",
+ "PerformanceManager" : "perfManager",
"PropertyCollector" : "propertyCollector",
"SearchIndex" : "searchIndex",
- "SessionManager" : "sessionManager" }
+ "SessionManager" : "sessionManager",
+ "VirtualDiskManager" : "virtualDiskManager" }
def __init__(self, type, name, occurrence):
self.type = type
@@ -1146,6 +1148,7 @@ additional_object_features = { "DatastoreHostMount"
: Object.FEATURE__DE
"SharesInfo" :
Object.FEATURE__ANY_TYPE,
"TaskInfo" :
Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
"UserSession" :
Object.FEATURE__ANY_TYPE,
+ "VirtualDiskSpec" :
Object.FEATURE__DYNAMIC_CAST,
"VirtualMachineQuestionInfo" :
Object.FEATURE__ANY_TYPE,
"VirtualMachineSnapshotTree" :
Object.FEATURE__DEEP_COPY | Object.FEATURE__ANY_TYPE }
diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c
index 56d2e58..a00561f 100644
--- a/src/esx/esx_vi_methods.c
+++ b/src/esx/esx_vi_methods.c
@@ -173,6 +173,12 @@
+#define ESX_VI__METHOD__PARAMETER__THIS__fileManager \
+ ESX_VI__METHOD__PARAMETER__THIS_FROM_SERVICE(ManagedObjectReference, \
+ fileManager)
+
+
+
#define ESX_VI__METHOD__PARAMETER__THIS__perfManager \
ESX_VI__METHOD__PARAMETER__THIS_FROM_SERVICE(ManagedObjectReference, \
perfManager)
@@ -197,6 +203,12 @@
+#define ESX_VI__METHOD__PARAMETER__THIS__virtualDiskManager \
+ ESX_VI__METHOD__PARAMETER__THIS_FROM_SERVICE(ManagedObjectReference, \
+ virtualDiskManager)
+
+
+
/*
* A required parameter must be != 0 (NULL for pointers, "undefined" == 0 for
* enumeration values).
--
1.7.0.4