mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 01:43:23 +00:00
storage: dir: adapt .uploadVol .dowloadVol for ploop volume
In case of ploop volume, target path of the volume is the path to the directory that contains image file named root.hds and DiskDescriptor.xml. While using uploadVol and downloadVol callbacks we need to open root.hds itself. Upload or download operations with ploop volume are only allowed when images do not have snapshots. Otherwise operation fails. Signed-off-by: Olga Krishtal <okrishtal@virtuozzo.com> Signed-off-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
ea94be4703
commit
03e750f35d
@ -2072,6 +2072,47 @@ virStorageBackendStablePath(virStoragePoolObjPtr pool,
|
||||
return stablepath;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the ploop image has snapshots.
|
||||
* return: -1 - failed to check
|
||||
* 0 - no snapshots
|
||||
* 1 - at least one snapshot
|
||||
*/
|
||||
static int
|
||||
virStorageBackendPloopHasSnapshots(char *path)
|
||||
{
|
||||
virCommandPtr cmd = NULL;
|
||||
char *output = NULL;
|
||||
char *snap_tool = NULL;
|
||||
int ret = -1;
|
||||
|
||||
snap_tool = virFindFileInPath("ploop");
|
||||
if (!snap_tool) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("unable to find ploop, please install "
|
||||
"ploop tools"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmd = virCommandNewArgList(snap_tool, "snapshot-list", NULL);
|
||||
virCommandAddArgFormat(cmd, "%s/DiskDescriptor.xml", path);
|
||||
virCommandSetOutputBuffer(cmd, &output);
|
||||
|
||||
if ((ret = virCommandRun(cmd, NULL)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!strstr(output, "root.hds.")) {
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(output);
|
||||
virCommandFree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
virStorageBackendVolUploadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
||||
@ -2081,12 +2122,41 @@ virStorageBackendVolUploadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
unsigned long long len,
|
||||
unsigned int flags)
|
||||
{
|
||||
char *path = NULL;
|
||||
char *target_path = vol->target.path;
|
||||
int ret = -1;
|
||||
int has_snap = 0;
|
||||
|
||||
virCheckFlags(0, -1);
|
||||
/* if volume has target format VIR_STORAGE_FILE_PLOOP
|
||||
* we need to restore DiskDescriptor.xml, according to
|
||||
* new contents of volume. This operation will be perfomed
|
||||
* when volUpload is fully finished. */
|
||||
if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
|
||||
/* Fail if the volume contains snapshots or we failed to check it.*/
|
||||
has_snap = virStorageBackendPloopHasSnapshots(vol->target.path);
|
||||
if (has_snap < 0) {
|
||||
goto cleanup;
|
||||
} else if (!has_snap) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("can't upload volume, all existing snapshots"
|
||||
" will be lost"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virAsprintf(&path, "%s/root.hds", vol->target.path) < 0)
|
||||
return -1;
|
||||
target_path = path;
|
||||
}
|
||||
|
||||
/* Not using O_CREAT because the file is required to already exist at
|
||||
* this point */
|
||||
return virFDStreamOpenBlockDevice(stream, vol->target.path,
|
||||
ret = virFDStreamOpenBlockDevice(stream, target_path,
|
||||
offset, len, O_WRONLY);
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
@ -2098,10 +2168,33 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
unsigned long long len,
|
||||
unsigned int flags)
|
||||
{
|
||||
virCheckFlags(0, -1);
|
||||
char *path = NULL;
|
||||
char *target_path = vol->target.path;
|
||||
int ret = -1;
|
||||
int has_snap = 0;
|
||||
|
||||
return virFDStreamOpenBlockDevice(stream, vol->target.path,
|
||||
virCheckFlags(0, -1);
|
||||
if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
|
||||
has_snap = virStorageBackendPloopHasSnapshots(vol->target.path);
|
||||
if (has_snap < 0) {
|
||||
goto cleanup;
|
||||
} else if (!has_snap) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("can't download volume, all existing snapshots"
|
||||
" will be lost"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (virAsprintf(&path, "%s/root.hds", vol->target.path) < 0)
|
||||
goto cleanup;
|
||||
target_path = path;
|
||||
}
|
||||
|
||||
ret = virFDStreamOpenBlockDevice(stream, target_path,
|
||||
offset, len, O_RDONLY);
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,6 +63,7 @@ typedef struct _virStorageVolStreamInfo virStorageVolStreamInfo;
|
||||
typedef virStorageVolStreamInfo *virStorageVolStreamInfoPtr;
|
||||
struct _virStorageVolStreamInfo {
|
||||
char *pool_name;
|
||||
char *vol_path;
|
||||
};
|
||||
|
||||
static void storageDriverLock(void)
|
||||
@ -2204,6 +2205,48 @@ virStorageVolPoolRefreshDataFree(void *opaque)
|
||||
VIR_FREE(cbdata);
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendPloopRestoreDesc(char *path)
|
||||
{
|
||||
int ret = -1;
|
||||
virCommandPtr cmd = NULL;
|
||||
char *refresh_tool = NULL;
|
||||
char *desc = NULL;
|
||||
|
||||
if (virAsprintf(&desc, "%s/DiskDescriptor.xml", path) < 0)
|
||||
return ret;
|
||||
|
||||
if (virFileRemove(desc, 0, 0) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("refresh ploop failed:"
|
||||
" unuble to delete DiskDescriptor.xml"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
refresh_tool = virFindFileInPath("ploop");
|
||||
if (!refresh_tool) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unable to find ploop, please install ploop tools"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cmd = virCommandNewArgList(refresh_tool, "restore-descriptor",
|
||||
path, NULL);
|
||||
virCommandAddArgFormat(cmd, "%s/root.hds", path);
|
||||
if (virCommandRun(cmd, NULL) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(refresh_tool);
|
||||
virCommandFree(cmd);
|
||||
VIR_FREE(desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Thread to handle the pool refresh
|
||||
*
|
||||
@ -2219,6 +2262,10 @@ virStorageVolPoolRefreshThread(void *opaque)
|
||||
virStorageBackendPtr backend;
|
||||
|
||||
storageDriverLock();
|
||||
if (cbdata->vol_path) {
|
||||
if (virStorageBackendPloopRestoreDesc(cbdata->vol_path) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(pool = virStoragePoolObjFindByName(&driver->pools,
|
||||
cbdata->pool_name)))
|
||||
goto cleanup;
|
||||
@ -2313,6 +2360,9 @@ storageVolUpload(virStorageVolPtr obj,
|
||||
if (VIR_ALLOC(cbdata) < 0 ||
|
||||
VIR_STRDUP(cbdata->pool_name, pool->def->name) < 0)
|
||||
goto cleanup;
|
||||
if (vol->target.type == VIR_STORAGE_VOL_PLOOP &&
|
||||
VIR_STRDUP(cbdata->vol_path, vol->target.path) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = backend->uploadVol(obj->conn, pool, vol, stream,
|
||||
|
Loading…
Reference in New Issue
Block a user