[libvirt] [PATCH] qemuDomainFSFreeze: report unless the agent supports mountpoints param

Tomoki Sekiyama tomoki.sekiyama at hds.com
Wed Aug 13 15:42:40 UTC 2014


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 at 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",




More information about the libvir-list mailing list