mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
virsh: Implement sparse stream to vol-download
Add a new --sparse switch that does nothing more than enables the sparse streams feature for this command. Among with the switch new helper function is introduced: virshStreamSkip(). This is the callback that is called whenever daemon sends us a hole. In the callback we reflect the hole in underlying file by seeking as many bytes as told. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
1f43aa67c5
commit
f03b44b2df
@ -153,6 +153,24 @@ virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED,
|
||||||
|
long long offset,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
int *fd = opaque;
|
||||||
|
off_t cur;
|
||||||
|
|
||||||
|
if ((cur = lseek(*fd, offset, SEEK_CUR)) == (off_t) -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ftruncate(*fd, cur) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
virshDomainFree(virDomainPtr dom)
|
virshDomainFree(virDomainPtr dom)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +57,11 @@ virshStreamSink(virStreamPtr st,
|
|||||||
size_t nbytes,
|
size_t nbytes,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
int
|
||||||
|
virshStreamSkip(virStreamPtr st,
|
||||||
|
long long offset,
|
||||||
|
void *opaque);
|
||||||
|
|
||||||
int
|
int
|
||||||
virshDomainGetXMLFromDom(vshControl *ctl,
|
virshDomainGetXMLFromDom(vshControl *ctl,
|
||||||
virDomainPtr dom,
|
virDomainPtr dom,
|
||||||
|
@ -763,6 +763,10 @@ static const vshCmdOptDef opts_vol_download[] = {
|
|||||||
.type = VSH_OT_INT,
|
.type = VSH_OT_INT,
|
||||||
.help = N_("amount of data to download")
|
.help = N_("amount of data to download")
|
||||||
},
|
},
|
||||||
|
{.name = "sparse",
|
||||||
|
.type = VSH_OT_BOOL,
|
||||||
|
.help = N_("preserve sparseness of volume")
|
||||||
|
},
|
||||||
{.name = NULL}
|
{.name = NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -778,6 +782,7 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
|
|||||||
unsigned long long offset = 0, length = 0;
|
unsigned long long offset = 0, length = 0;
|
||||||
bool created = false;
|
bool created = false;
|
||||||
virshControlPtr priv = ctl->privData;
|
virshControlPtr priv = ctl->privData;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0)
|
if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0)
|
||||||
return false;
|
return false;
|
||||||
@ -791,6 +796,9 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
|
|||||||
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
|
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (vshCommandOptBool(cmd, "sparse"))
|
||||||
|
flags |= VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM;
|
||||||
|
|
||||||
if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) {
|
if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) {
|
||||||
if (errno != EEXIST ||
|
if (errno != EEXIST ||
|
||||||
(fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) {
|
(fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) {
|
||||||
@ -806,12 +814,12 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virStorageVolDownload(vol, st, offset, length, 0) < 0) {
|
if (virStorageVolDownload(vol, st, offset, length, flags) < 0) {
|
||||||
vshError(ctl, _("cannot download from volume %s"), name);
|
vshError(ctl, _("cannot download from volume %s"), name);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virStreamRecvAll(st, virshStreamSink, &fd) < 0) {
|
if (virStreamSparseRecvAll(st, virshStreamSink, virshStreamSkip, &fd) < 0) {
|
||||||
vshError(ctl, _("cannot receive data from volume %s"), name);
|
vshError(ctl, _("cannot receive data from volume %s"), name);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -3943,12 +3943,13 @@ regarding possible target volume and pool changes as a result of the
|
|||||||
pool refresh when the upload is attempted.
|
pool refresh when the upload is attempted.
|
||||||
|
|
||||||
=item B<vol-download> [I<--pool> I<pool-or-uuid>] [I<--offset> I<bytes>]
|
=item B<vol-download> [I<--pool> I<pool-or-uuid>] [I<--offset> I<bytes>]
|
||||||
[I<--length> I<bytes>] I<vol-name-or-key-or-path> I<local-file>
|
[I<--length> I<bytes>] [I<--sparse>] I<vol-name-or-key-or-path> I<local-file>
|
||||||
|
|
||||||
Download the contents of a storage volume to I<local-file>.
|
Download the contents of a storage volume to I<local-file>.
|
||||||
I<--pool> I<pool-or-uuid> is the name or UUID of the storage pool the volume
|
I<--pool> I<pool-or-uuid> is the name or UUID of the storage pool the volume
|
||||||
is in.
|
is in.
|
||||||
I<vol-name-or-key-or-path> is the name or key or path of the volume to download.
|
I<vol-name-or-key-or-path> is the name or key or path of the volume to download.
|
||||||
|
If I<--sparse> is specified, this command will preserve volume sparseness.
|
||||||
I<--offset> is the position in the storage volume at which to start reading
|
I<--offset> is the position in the storage volume at which to start reading
|
||||||
the data. The value must be 0 or larger. I<--length> is an upper bound of
|
the data. The value must be 0 or larger. I<--length> is an upper bound of
|
||||||
the amount of data to be downloaded. A negative value is interpreted as
|
the amount of data to be downloaded. A negative value is interpreted as
|
||||||
|
Loading…
Reference in New Issue
Block a user