esx: Add support for storage volume cloning

This commit is contained in:
Matthias Bolte 2010-12-06 21:07:35 +01:00
parent 6679943f94
commit e3fb2908cb
2 changed files with 208 additions and 1 deletions

View File

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

View File

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