mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00: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 */
|
"reboot-timeout", /* 110 */
|
||||||
"dump-guest-core",
|
"dump-guest-core",
|
||||||
"seamless-migration",
|
"seamless-migration",
|
||||||
|
"block-commit",
|
||||||
);
|
);
|
||||||
|
|
||||||
struct _qemuCaps {
|
struct _qemuCaps {
|
||||||
@ -1881,6 +1882,8 @@ qemuCapsProbeQMPCommands(qemuCapsPtr caps,
|
|||||||
qemuCapsSet(caps, QEMU_CAPS_SPICE);
|
qemuCapsSet(caps, QEMU_CAPS_SPICE);
|
||||||
else if (STREQ(name, "query-kvm"))
|
else if (STREQ(name, "query-kvm"))
|
||||||
qemuCapsSet(caps, QEMU_CAPS_KVM);
|
qemuCapsSet(caps, QEMU_CAPS_KVM);
|
||||||
|
else if (STREQ(name, "block-commit"))
|
||||||
|
qemuCapsSet(caps, QEMU_CAPS_BLOCK_COMMIT);
|
||||||
VIR_FREE(name);
|
VIR_FREE(name);
|
||||||
}
|
}
|
||||||
VIR_FREE(commands);
|
VIR_FREE(commands);
|
||||||
|
@ -150,6 +150,7 @@ enum qemuCapsFlags {
|
|||||||
QEMU_CAPS_REBOOT_TIMEOUT = 110, /* -boot reboot-timeout */
|
QEMU_CAPS_REBOOT_TIMEOUT = 110, /* -boot reboot-timeout */
|
||||||
QEMU_CAPS_DUMP_GUEST_CORE = 111, /* dump-guest-core-parameter */
|
QEMU_CAPS_DUMP_GUEST_CORE = 111, /* dump-guest-core-parameter */
|
||||||
QEMU_CAPS_SEAMLESS_MIGRATION = 112, /* seamless-migration for SPICE */
|
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 */
|
QEMU_CAPS_LAST, /* this must always be the last item */
|
||||||
};
|
};
|
||||||
|
@ -2796,6 +2796,36 @@ qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
|
|||||||
return ret;
|
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,
|
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd,
|
const char *cmd,
|
||||||
char **reply,
|
char **reply,
|
||||||
|
@ -524,6 +524,13 @@ int qemuMonitorDiskSnapshot(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
|
int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
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,
|
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd,
|
const char *cmd,
|
||||||
char **reply,
|
char **reply,
|
||||||
|
@ -805,6 +805,8 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
if (STREQ(type_str, "stream"))
|
if (STREQ(type_str, "stream"))
|
||||||
type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
|
type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
|
||||||
|
else if (STREQ(type_str, "commit"))
|
||||||
|
type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
|
||||||
|
|
||||||
switch ((virConnectDomainEventBlockJobStatus) event) {
|
switch ((virConnectDomainEventBlockJobStatus) event) {
|
||||||
case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
|
case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
|
||||||
@ -3275,6 +3277,36 @@ cleanup:
|
|||||||
return ret;
|
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,
|
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd_str,
|
const char *cmd_str,
|
||||||
char **reply_str,
|
char **reply_str,
|
||||||
@ -3391,6 +3423,8 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
|||||||
}
|
}
|
||||||
if (STREQ(type, "stream"))
|
if (STREQ(type, "stream"))
|
||||||
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
|
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
|
||||||
|
else if (STREQ(type, "commit"))
|
||||||
|
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
|
||||||
else
|
else
|
||||||
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||||
|
|
||||||
|
@ -235,6 +235,13 @@ int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon,
|
|||||||
bool reuse);
|
bool reuse);
|
||||||
int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions);
|
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,
|
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd_str,
|
const char *cmd_str,
|
||||||
char **reply_str,
|
char **reply_str,
|
||||||
|
@ -909,12 +909,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
if (disk) {
|
if (disk) {
|
||||||
path = disk->src;
|
path = disk->src;
|
||||||
event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
|
event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
|
||||||
/* XXX If we completed a block pull, then recompute the cached
|
/* XXX If we completed a block pull or commit, then recompute
|
||||||
* backing chain to match. Better would be storing the chain
|
* the cached backing chain to match. Better would be storing
|
||||||
* ourselves rather than reprobing, but this requires
|
* the chain ourselves rather than reprobing, but this
|
||||||
* modifying domain_conf and our XML to fully track the chain
|
* requires modifying domain_conf and our XML to fully track
|
||||||
* across libvirtd restarts. */
|
* the chain across libvirtd restarts. For that matter, if
|
||||||
if (type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL &&
|
* 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)
|
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
|
||||||
qemuDomainDetermineDiskChain(driver, disk, true);
|
qemuDomainDetermineDiskChain(driver, disk, true);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user