This patch gives users a nicer error message when the QEMU guest agent is
not new enough to support 'guest-fsfreeze-freeze-list' command, which is
used by qemuDomainFSFreeze() to freeze specified filesystems only.
Before this patch, it was depending on the agent to complain about unknown
command:
# virsh domfsfreeze domain --mountpoint /mnt/point
error: Unable to freeze filesystems
error: internal error: unable to execute QEMU agent command 'guest-
fsfreeze-freeze-list': The command guest-fsfreeze-freeze-list has not been
found
After:
# virsh domfsfreeze domain --mountpoint /mnt/point
error: Unable to freeze filesystems
error: argument unsupported: this version of guest agent doesn't support
specifying mountpoints
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama(a)hds.com>
---
src/qemu/qemu_agent.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index a10954a..8102b36 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1279,6 +1279,75 @@ void qemuAgentNotifyEvent(qemuAgentPtr mon,
}
}
+static int qemuAgentCommandSupported(qemuAgentPtr mon,
+ const char *cmdname)
+{
+ int ret = -1;
+ size_t i;
+ int ndata;
+ virJSONValuePtr cmd;
+ virJSONValuePtr data;
+ virJSONValuePtr reply = NULL;
+
+ cmd = qemuAgentMakeCommand("guest-info", NULL);
+ if (!cmd)
+ return -1;
+
+ if (qemuAgentCommand(mon, cmd, &reply, false,
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+ goto cleanup;
+
+ if (!(data = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest-info reply was missing return data"));
+ goto cleanup;
+ }
+
+ if (!(data = virJSONValueObjectGet(data, "supported_commands"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest-info reply was missing supported_commands"));
+ goto cleanup;
+ }
+
+ if (data->type != VIR_JSON_TYPE_ARRAY) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest-info supported_commands was not an array"));
+ goto cleanup;
+ }
+
+ ndata = virJSONValueArraySize(data);
+
+ for (i = 0; i < ndata; i++) {
+ virJSONValuePtr entry = virJSONValueArrayGet(data, i);
+ const char *name;
+
+ if (!entry) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("array element missing in guest-info "
+ "supported_commands"));
+ goto cleanup;
+ }
+
+ if (!(name = virJSONValueObjectGetString(entry, "name"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest-info supported_commands was missing
name"));
+ goto cleanup;
+ }
+
+ if (strcmp(name, cmdname) == 0) {
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
VIR_ENUM_DECL(qemuAgentShutdownMode);
VIR_ENUM_IMPL(qemuAgentShutdownMode,
@@ -1346,8 +1415,16 @@ int qemuAgentFSFreeze(qemuAgentPtr mon, const char **mountpoints,
return -1;
if (qemuAgentCommand(mon, cmd, &reply, true,
- VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
+ if (mountpoints && nmountpoints) {
+ if (qemuAgentCommandSupported(mon,
+ "guest-fsfreeze-freeze-list") == 0)
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("this version of guest agent doesn't support
"
+ "specifying mountpoints"));
+ }
goto cleanup;
+ }
if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",