mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-04 21:47:16 +03:00
blockjob: manage qemu block-commit monitor command
qemu 1.3 will be adding a 'block-commit' monitor command, per qemu.git commit ed61fc1. It matches nicely to the libvirt API virDomainBlockCommit. * src/qemu/qemu_capabilities.h (QEMU_CAPS_BLOCK_COMMIT): New bit. * src/qemu/qemu_capabilities.c (qemuCapsProbeQMPCommands): Set it. * src/qemu/qemu_monitor.h (qemuMonitorBlockCommit): New prototype. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit): Likewise. * src/qemu/qemu_monitor.c (qemuMonitorBlockCommit): Implement it. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit): Likewise. (qemuMonitorJSONHandleBlockJobImpl) (qemuMonitorJSONGetBlockJobInfoOne): Handle new event type.
This commit is contained in:
parent
67aea3fb78
commit
3f38c7e3a9
@ -187,6 +187,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
|
||||
"reboot-timeout", /* 110 */
|
||||
"dump-guest-core",
|
||||
"seamless-migration",
|
||||
"block-commit",
|
||||
);
|
||||
|
||||
struct _qemuCaps {
|
||||
@ -1881,6 +1882,8 @@ qemuCapsProbeQMPCommands(qemuCapsPtr caps,
|
||||
qemuCapsSet(caps, QEMU_CAPS_SPICE);
|
||||
else if (STREQ(name, "query-kvm"))
|
||||
qemuCapsSet(caps, QEMU_CAPS_KVM);
|
||||
else if (STREQ(name, "block-commit"))
|
||||
qemuCapsSet(caps, QEMU_CAPS_BLOCK_COMMIT);
|
||||
VIR_FREE(name);
|
||||
}
|
||||
VIR_FREE(commands);
|
||||
|
@ -150,6 +150,7 @@ enum qemuCapsFlags {
|
||||
QEMU_CAPS_REBOOT_TIMEOUT = 110, /* -boot reboot-timeout */
|
||||
QEMU_CAPS_DUMP_GUEST_CORE = 111, /* dump-guest-core-parameter */
|
||||
QEMU_CAPS_SEAMLESS_MIGRATION = 112, /* seamless-migration for SPICE */
|
||||
QEMU_CAPS_BLOCK_COMMIT = 113, /* block-commit */
|
||||
|
||||
QEMU_CAPS_LAST, /* this must always be the last item */
|
||||
};
|
||||
|
@ -2796,6 +2796,36 @@ qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start a block-commit block job. bandwidth is in MB/sec. */
|
||||
int
|
||||
qemuMonitorBlockCommit(qemuMonitorPtr mon, const char *device,
|
||||
const char *top, const char *base,
|
||||
unsigned long bandwidth)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned long long speed;
|
||||
|
||||
VIR_DEBUG("mon=%p, device=%s, top=%s, base=%s, bandwidth=%ld",
|
||||
mon, device, NULLSTR(top), NULLSTR(base), bandwidth);
|
||||
|
||||
/* Convert bandwidth MiB to bytes */
|
||||
speed = bandwidth;
|
||||
if (speed > ULLONG_MAX / 1024 / 1024) {
|
||||
virReportError(VIR_ERR_OVERFLOW,
|
||||
_("bandwidth must be less than %llu"),
|
||||
ULLONG_MAX / 1024 / 1024);
|
||||
return -1;
|
||||
}
|
||||
speed <<= 20;
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONBlockCommit(mon, device, top, base, speed);
|
||||
else
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("block-commit requires JSON monitor"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd,
|
||||
char **reply,
|
||||
|
@ -524,6 +524,13 @@ int qemuMonitorDiskSnapshot(qemuMonitorPtr mon,
|
||||
int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuMonitorBlockCommit(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *top,
|
||||
const char *base,
|
||||
unsigned long bandwidth)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd,
|
||||
char **reply,
|
||||
|
@ -805,6 +805,8 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
|
||||
|
||||
if (STREQ(type_str, "stream"))
|
||||
type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
|
||||
else if (STREQ(type_str, "commit"))
|
||||
type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
|
||||
|
||||
switch ((virConnectDomainEventBlockJobStatus) event) {
|
||||
case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
|
||||
@ -3275,6 +3277,36 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* speed is in bytes/sec */
|
||||
int
|
||||
qemuMonitorJSONBlockCommit(qemuMonitorPtr mon, const char *device,
|
||||
const char *top, const char *base,
|
||||
unsigned long long speed)
|
||||
{
|
||||
int ret = -1;
|
||||
virJSONValuePtr cmd;
|
||||
virJSONValuePtr reply = NULL;
|
||||
|
||||
cmd = qemuMonitorJSONMakeCommand("block-commit",
|
||||
"s:device", device,
|
||||
"U:speed", speed,
|
||||
"s:top", top,
|
||||
base ? "s:base" : NULL, base,
|
||||
NULL);
|
||||
if (!cmd)
|
||||
return -1;
|
||||
|
||||
if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
|
||||
goto cleanup;
|
||||
ret = qemuMonitorJSONCheckError(cmd, reply);
|
||||
|
||||
cleanup:
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd_str,
|
||||
char **reply_str,
|
||||
@ -3391,6 +3423,8 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
||||
}
|
||||
if (STREQ(type, "stream"))
|
||||
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
|
||||
else if (STREQ(type, "commit"))
|
||||
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
|
||||
else
|
||||
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||
|
||||
|
@ -235,6 +235,13 @@ int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon,
|
||||
bool reuse);
|
||||
int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions);
|
||||
|
||||
int qemuMonitorJSONBlockCommit(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *top,
|
||||
const char *base,
|
||||
unsigned long long bandwidth)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd_str,
|
||||
char **reply_str,
|
||||
|
@ -909,12 +909,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
if (disk) {
|
||||
path = disk->src;
|
||||
event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
|
||||
/* XXX If we completed a block pull, then recompute the cached
|
||||
* backing chain to match. Better would be storing the chain
|
||||
* ourselves rather than reprobing, but this requires
|
||||
* modifying domain_conf and our XML to fully track the chain
|
||||
* across libvirtd restarts. */
|
||||
if (type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL &&
|
||||
/* XXX If we completed a block pull or commit, then recompute
|
||||
* the cached backing chain to match. Better would be storing
|
||||
* the chain ourselves rather than reprobing, but this
|
||||
* requires modifying domain_conf and our XML to fully track
|
||||
* the chain across libvirtd restarts. For that matter, if
|
||||
* qemu gains support for committing the active layer, we have
|
||||
* to update disk->src. */
|
||||
if ((type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL ||
|
||||
type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
|
||||
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
|
||||
qemuDomainDetermineDiskChain(driver, disk, true);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user