mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-25 01:34:11 +03:00
esx: Add support for storage volume cloning
This commit is contained in:
parent
6679943f94
commit
e3fb2908cb
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user