esx: Add .vmdk storage volume creation

This commit is contained in:
Matthias Bolte 2010-08-28 21:49:07 +02:00
parent 9a4b705f74
commit e5a3c0b35d
7 changed files with 293 additions and 31 deletions

View File

@ -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;
}

View File

@ -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,207 @@ 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 *tmp;
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 */
tmp = strrchr(def->name, '/');
if (tmp == NULL || *def->name == '/' || tmp[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 specify 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 +984,7 @@ esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
}
if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
&fileInfo,
false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
@ -875,7 +1077,7 @@ esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int flags)
}
if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
&fileInfo,
false, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
@ -986,7 +1188,7 @@ static virStorageDriver esxStorageDriver = {
esxStorageVolumeLookupByName, /* volLookupByName */
esxStorageVolumeLookupByKeyOrPath, /* volLookupByKey */
esxStorageVolumeLookupByKeyOrPath, /* volLookupByPath */
NULL, /* volCreateXML */
esxStorageVolumeCreateXML, /* volCreateXML */
NULL, /* volCreateXMLFrom */
NULL, /* volDelete */
NULL, /* volWipe */

View File

@ -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) {

View File

@ -401,6 +401,7 @@ int esxVI_LookupCurrentSnapshotTree
int esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
const char *datastorePath,
bool lookupFolder,
esxVI_FileInfo **fileInfo,
esxVI_Occurrence occurrence);

View File

@ -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

View File

@ -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
@ -1158,6 +1160,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 }

View File

@ -175,6 +175,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)
@ -199,6 +205,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).