--- src/esx/esx_storage_driver.c | 198 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi_generator.input | 11 ++ 2 files changed, 208 insertions(+), 1 deletions(-) diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c index 9165f7a..e6803c2 100644 --- a/src/esx/esx_storage_driver.c +++ b/src/esx/esx_storage_driver.c @@ -1180,6 +1180,202 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc, +static virStorageVolPtr +esxStorageVolumeCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc, + virStorageVolPtr sourceVolume, unsigned int flags) +{ + virStorageVolPtr volume = NULL; + esxPrivate *priv = pool->conn->storagePrivateData; + virStoragePoolDef poolDef; + char *sourceDatastorePath = NULL; + virStorageVolDefPtr def = NULL; + char *tmp; + char *unescapedDatastorePath = NULL; + char *unescapedDirectoryName = NULL; + char *unescapedDirectoryAndFileName = NULL; + char *directoryName = NULL; + char *fileName = NULL; + char *datastorePathWithoutFileName = NULL; + char *datastorePath = NULL; + esxVI_FileInfo *fileInfo = NULL; + esxVI_ManagedObjectReference *task = NULL; + esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; + char *uuid_string = NULL; + char *key = NULL; + + virCheckFlags(0, NULL); + + memset(&poolDef, 0, sizeof (poolDef)); + + if (esxVI_EnsureSession(priv->primary) < 0) { + return NULL; + } + + if (esxStoragePoolLookupType(priv->primary, pool->name, &poolDef.type) < 0) { + return NULL; + } + + if (virAsprintf(&sourceDatastorePath, "[%s] %s", sourceVolume->pool, + sourceVolume->name) < 0) { + virReportOOMError(); + 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(&unescapedDatastorePath, "[%s] %s", pool->name, + def->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (def->target.format == VIR_STORAGE_FILE_VMDK) { + /* Parse and escape datastore path */ + if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL, + &unescapedDirectoryName, + &unescapedDirectoryAndFileName) < 0) { + goto cleanup; + } + + directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName); + + if (directoryName == NULL) { + goto cleanup; + } + + fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName + + strlen(unescapedDirectoryName) + 1); + + if (fileName == NULL) { + goto cleanup; + } + + if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name, + directoryName) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName, + fileName) < 0) { + virReportOOMError(); + goto cleanup; + } + + /* Create directory, if it doesn't exist yet */ + 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; + } + } + + /* Copy VirtualDisk */ + if (esxVI_CopyVirtualDisk_Task(priv->primary, sourceDatastorePath, + priv->primary->datacenter->_reference, + datastorePath, + priv->primary->datacenter->_reference, + NULL, esxVI_Boolean_False, &task) < 0 || + esxVI_WaitForTaskCompletion(priv->primary, task, NULL, + esxVI_Occurrence_None, + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { + goto cleanup; + } + + if (taskInfoState != esxVI_TaskInfoState_Success) { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not copy volume: %s"), + taskInfoErrorMessage); + goto cleanup; + } + + if (priv->primary->hasQueryVirtualDiskUuid) { + if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath, + priv->primary->datacenter->_reference, + &uuid_string) < 0) { + goto cleanup; + } + + if (esxUtil_ReformatUuid(uuid_string, key) < 0) { + goto cleanup; + } + } else { + /* Fall back to the path as key */ + if (esxVI_String_DeepCopyValue(&key, datastorePath) < 0) { + 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, key); + + cleanup: + VIR_FREE(sourceDatastorePath); + virStorageVolDefFree(def); + VIR_FREE(unescapedDatastorePath); + VIR_FREE(unescapedDirectoryName); + VIR_FREE(unescapedDirectoryAndFileName); + VIR_FREE(directoryName); + VIR_FREE(fileName); + VIR_FREE(datastorePathWithoutFileName); + VIR_FREE(datastorePath); + esxVI_FileInfo_Free(&fileInfo); + esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); + VIR_FREE(uuid_string); + VIR_FREE(key); + + return volume; +} + + + static int esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info) { @@ -1377,7 +1573,7 @@ static virStorageDriver esxStorageDriver = { esxStorageVolumeLookupByKey, /* volLookupByKey */ esxStorageVolumeLookupByPath, /* volLookupByPath */ esxStorageVolumeCreateXML, /* volCreateXML */ - NULL, /* volCreateXMLFrom */ + esxStorageVolumeCreateXMLFrom, /* volCreateXMLFrom */ NULL, /* volDelete */ NULL, /* volWipe */ esxStorageVolumeGetInfo, /* volGetInfo */ diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 991ce8a..4018c6e 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -700,6 +700,17 @@ method CancelTask end +method CopyVirtualDisk_Task returns ManagedObjectReference r + ManagedObjectReference _this:VirtualDiskManager r + String sourceName r + ManagedObjectReference sourceDatacenter o + String destName r + ManagedObjectReference destDatacenter o + VirtualDiskSpec destSpec o + Boolean force o +end + + method CreateFilter returns ManagedObjectReference r ManagedObjectReference _this:PropertyCollector r PropertyFilterSpec spec r -- 1.7.0.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list