mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-12 13:17:58 +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
|
static int
|
||||||
esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
|
esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
|
||||||
{
|
{
|
||||||
@ -1377,7 +1573,7 @@ static virStorageDriver esxStorageDriver = {
|
|||||||
esxStorageVolumeLookupByKey, /* volLookupByKey */
|
esxStorageVolumeLookupByKey, /* volLookupByKey */
|
||||||
esxStorageVolumeLookupByPath, /* volLookupByPath */
|
esxStorageVolumeLookupByPath, /* volLookupByPath */
|
||||||
esxStorageVolumeCreateXML, /* volCreateXML */
|
esxStorageVolumeCreateXML, /* volCreateXML */
|
||||||
NULL, /* volCreateXMLFrom */
|
esxStorageVolumeCreateXMLFrom, /* volCreateXMLFrom */
|
||||||
NULL, /* volDelete */
|
NULL, /* volDelete */
|
||||||
NULL, /* volWipe */
|
NULL, /* volWipe */
|
||||||
esxStorageVolumeGetInfo, /* volGetInfo */
|
esxStorageVolumeGetInfo, /* volGetInfo */
|
||||||
|
@ -700,6 +700,17 @@ method CancelTask
|
|||||||
end
|
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
|
method CreateFilter returns ManagedObjectReference r
|
||||||
ManagedObjectReference _this:PropertyCollector r
|
ManagedObjectReference _this:PropertyCollector r
|
||||||
PropertyFilterSpec spec r
|
PropertyFilterSpec spec r
|
||||||
|
Loading…
Reference in New Issue
Block a user