]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add API to change qemu agent response timeout
authorJonathon Jongsma <jjongsma@redhat.com>
Wed, 13 Nov 2019 22:06:09 +0000 (16:06 -0600)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 14 Nov 2019 18:10:01 +0000 (19:10 +0100)
Some layered products such as oVirt have requested a way to avoid being
blocked by guest agent commands when querying a loaded vm. For example,
many guest agent commands are polled periodically to monitor changes,
and rather than blocking the calling process, they'd prefer to simply
time out when an agent query is taking too long.

This patch adds a way for the user to specify a custom agent timeout
that is applied to all agent commands.

One special case to note here is the 'guest-sync' command. 'guest-sync'
is issued internally prior to calling any other command. (For example,
when libvirt wants to call 'guest-get-fsinfo', we first call
'guest-sync' and then call 'guest-get-fsinfo').

Previously, the 'guest-sync' command used a 5-second timeout
(VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT), whereas the actual command that
followed always blocked indefinitely
(VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK). As part of this patch, if a
custom timeout is specified that is shorter than
5 seconds,  this new timeout is also used for 'guest-sync'. If there is
no custom timeout or if the custom timeout is longer than 5 seconds, we
will continue to use the 5-second timeout.

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
24 files changed:
include/libvirt/libvirt-domain.h
include/libvirt/libvirt-qemu.h
src/driver-hypervisor.h
src/libvirt-domain.c
src/libvirt_public.syms
src/qemu/qemu_agent.c
src/qemu/qemu_agent.h
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
tests/qemustatusxml2xmldata/blockjob-mirror-in.xml
tests/qemustatusxml2xmldata/disk-secinfo-upgrade-out.xml
tests/qemustatusxml2xmldata/migration-in-params-in.xml
tests/qemustatusxml2xmldata/migration-out-nbd-out.xml
tests/qemustatusxml2xmldata/migration-out-nbd-tls-out.xml
tests/qemustatusxml2xmldata/migration-out-params-in.xml
tests/qemustatusxml2xmldata/modern-in.xml
tests/qemustatusxml2xmldata/vcpus-multi-in.xml
tools/virsh-domain.c
tools/virsh.pod

index 22277b0a84eadd7aec858953ff0a961ca62318b7..a2f007568c8831873c549401564eef423dca4468 100644 (file)
@@ -4916,4 +4916,14 @@ int virDomainGetGuestInfo(virDomainPtr domain,
                           int *nparams,
                           unsigned int flags);
 
+typedef enum {
+    VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK = -2,
+    VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_DEFAULT = -1,
+    VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_NOWAIT = 0,
+} virDomainAgentResponseTimeoutValues;
+
+int virDomainAgentSetResponseTimeout(virDomainPtr domain,
+                                     int timeout,
+                                     unsigned int flags);
+
 #endif /* LIBVIRT_DOMAIN_H */
index 891617443f44c74f14dc12ee44aee985b816f38e..0cc2872821c96704f27978846974a8a0dd7c2892 100644 (file)
@@ -43,10 +43,10 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain,
                                  unsigned int flags);
 
 typedef enum {
-    VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN = -2,
-    VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -2,
-    VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT = -1,
-    VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0,
+    VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN = VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK,
+    VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK,
+    VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT = VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_DEFAULT,
+    VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_NOWAIT,
     VIR_DOMAIN_QEMU_AGENT_COMMAND_SHUTDOWN = 60,
 } virDomainQemuAgentCommandTimeoutValues;
 
index 015b2cd01c907479f1780e2b7f9730bd73cdaa19..4afd8f6ec5f46b8714452cd609b6358f442357c8 100644 (file)
@@ -1372,6 +1372,11 @@ typedef int
                             int *nparams,
                             unsigned int flags);
 
+typedef int
+(*virDrvDomainAgentSetResponseTimeout)(virDomainPtr domain,
+                                       int timeout,
+                                       unsigned int flags);
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1632,4 +1637,5 @@ struct _virHypervisorDriver {
     virDrvDomainCheckpointGetParent domainCheckpointGetParent;
     virDrvDomainCheckpointDelete domainCheckpointDelete;
     virDrvDomainGetGuestInfo domainGetGuestInfo;
+    virDrvDomainAgentSetResponseTimeout domainAgentSetResponseTimeout;
 };
index dcab179e6e0531c202ae27c6dd775d1e676e3926..02622cb2ca67853b93b79183441940a59531fdce 100644 (file)
@@ -12497,3 +12497,52 @@ int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
     virDispatchError(domain->conn);
     return -1;
 }
+
+
+/**
+ * virDomainAgentSetResponseTimeout:
+ * @domain: a domain object
+ * @timeout: timeout in seconds
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Set how long to wait for a response from guest agent commands. By default,
+ * agent commands block forever waiting for a response.
+ *
+ * @timeout must be a value from virDomainAgentCommandTimeoutValues or
+ * positive:
+ *
+ *   VIR_DOMAIN_AGENT_COMMAND_TIMEOUT_BLOCK(-2): meaning to block forever
+ *      waiting for a result.
+ *   VIR_DOMAIN_AGENT_COMMAND_TIMEOUT_DEFAULT(-1): use default timeout value.
+ *   VIR_DOMAIN_AGENT_COMMAND_TIMEOUT_NOWAIT(0): does not wait.
+ *   positive value: wait for @timeout seconds
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+virDomainAgentSetResponseTimeout(virDomainPtr domain,
+                                 int timeout,
+                                 unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "timeout=%i, flags=0x%x",
+                     timeout, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+    conn = domain->conn;
+
+    if (conn->driver->domainAgentSetResponseTimeout) {
+        if (conn->driver->domainAgentSetResponseTimeout(domain, timeout, flags) < 0)
+            goto error;
+        return 0;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(conn);
+    return -1;
+}
index f88a77892f5352b589eb5d0656ac0c7520d02983..c92f083758e4bd881c07d587d30c7f1b1e6059a4 100644 (file)
@@ -862,4 +862,9 @@ LIBVIRT_5.8.0 {
         virConnectSetIdentity;
 } LIBVIRT_5.7.0;
 
+LIBVIRT_5.10.0 {
+    global:
+        virDomainAgentSetResponseTimeout;
+} LIBVIRT_5.8.0;
+
 # .... define new API here using predicted next version number ....
index 5a50f7f3be7f0452d625a50928101e1f0c554847..7905a74f9014de5c9713a99c8576a79cc6487282 100644 (file)
@@ -30,6 +30,7 @@
 #include <sys/time.h>
 
 #include "qemu_agent.h"
+#include "qemu_domain.h"
 #include "viralloc.h"
 #include "virlog.h"
 #include "virerror.h"
@@ -127,6 +128,7 @@ struct _qemuAgent {
      * but fire up an event on qemu monitor instead.
      * Take that as indication of successful completion */
     qemuAgentEvent await_event;
+    int timeout;
 };
 
 static virClassPtr qemuAgentClass;
@@ -695,6 +697,7 @@ qemuAgentOpen(virDomainObjPtr vm,
     if (!(mon = virObjectLockableNew(qemuAgentClass)))
         return NULL;
 
+    mon->timeout = QEMU_DOMAIN_PRIVATE(vm)->agentTimeout;
     mon->fd = -1;
     if (virCondInit(&mon->notify) < 0) {
         virReportSystemError(errno, "%s",
@@ -907,6 +910,12 @@ qemuAgentGuestSync(qemuAgentPtr mon)
     int send_ret;
     unsigned long long id;
     qemuAgentMessage sync_msg;
+    int timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT;
+
+    /* if user specified a custom agent timeout that is lower than the
+     * default timeout, use the shorter timeout instead */
+    if ((mon->timeout >= 0) && (mon->timeout < timeout))
+        timeout = mon->timeout;
 
     memset(&sync_msg, 0, sizeof(sync_msg));
     /* set only on first sync */
@@ -925,8 +934,7 @@ qemuAgentGuestSync(qemuAgentPtr mon)
 
     VIR_DEBUG("Sending guest-sync command with ID: %llu", id);
 
-    send_ret = qemuAgentSend(mon, &sync_msg,
-                             VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT);
+    send_ret = qemuAgentSend(mon, &sync_msg, timeout);
 
     VIR_DEBUG("qemuAgentSend returned: %d", send_ret);
 
@@ -1301,8 +1309,7 @@ int qemuAgentFSFreeze(qemuAgentPtr mon, const char **mountpoints,
     if (!cmd)
         goto cleanup;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) {
@@ -1339,8 +1346,7 @@ int qemuAgentFSThaw(qemuAgentPtr mon)
     if (!cmd)
         return -1;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) {
@@ -1377,8 +1383,7 @@ qemuAgentSuspend(qemuAgentPtr mon,
         return -1;
 
     mon->await_event = QEMU_AGENT_EVENT_SUSPEND;
-    ret = qemuAgentCommand(mon, cmd, &reply, false,
-                           VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK);
+    ret = qemuAgentCommand(mon, cmd, &reply, false, mon->timeout);
 
     virJSONValueFree(cmd);
     virJSONValueFree(reply);
@@ -1434,8 +1439,7 @@ qemuAgentFSTrim(qemuAgentPtr mon,
     if (!cmd)
         return ret;
 
-    ret = qemuAgentCommand(mon, cmd, &reply, false,
-                           VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK);
+    ret = qemuAgentCommand(mon, cmd, &reply, false, mon->timeout);
 
     virJSONValueFree(cmd);
     virJSONValueFree(reply);
@@ -1456,8 +1460,7 @@ qemuAgentGetVCPUs(qemuAgentPtr mon,
     if (!(cmd = qemuAgentMakeCommand("guest-get-vcpus", NULL)))
         return -1;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
@@ -1572,8 +1575,7 @@ qemuAgentSetVCPUsCommand(qemuAgentPtr mon,
                                      NULL)))
         goto cleanup;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     /* All negative values are invalid. Return of 0 is bogus since we wouldn't
@@ -1728,8 +1730,7 @@ qemuAgentGetHostname(qemuAgentPtr mon,
     if (!cmd)
         return ret;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0) {
         if (qemuAgentErrorCommandUnsupported(reply))
             ret = -2;
         goto cleanup;
@@ -1773,8 +1774,7 @@ qemuAgentGetTime(qemuAgentPtr mon,
     if (!cmd)
         return ret;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     if (virJSONValueObjectGetNumberUlong(reply, "return", &json_time) < 0) {
@@ -1839,8 +1839,7 @@ qemuAgentSetTime(qemuAgentPtr mon,
     if (!cmd)
         return ret;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     ret = 0;
@@ -2043,8 +2042,7 @@ qemuAgentGetFSInfoInternal(qemuAgentPtr mon,
     if (!cmd)
         return ret;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0) {
         if (qemuAgentErrorCommandUnsupported(reply))
             ret = -2;
         goto cleanup;
@@ -2333,8 +2331,7 @@ qemuAgentGetInterfaces(qemuAgentPtr mon,
     if (!(cmd = qemuAgentMakeCommand("guest-network-get-interfaces", NULL)))
         goto cleanup;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     if (!(ret_array = virJSONValueObjectGet(reply, "return"))) {
@@ -2511,8 +2508,7 @@ qemuAgentSetUserPassword(qemuAgentPtr mon,
                                      NULL)))
         goto cleanup;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0)
         goto cleanup;
 
     ret = 0;
@@ -2543,8 +2539,7 @@ qemuAgentGetUsers(qemuAgentPtr mon,
     if (!(cmd = qemuAgentMakeCommand("guest-get-users", NULL)))
         return -1;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0) {
         if (qemuAgentErrorCommandUnsupported(reply))
             return -2;
         return -1;
@@ -2633,8 +2628,7 @@ qemuAgentGetOSInfo(qemuAgentPtr mon,
     if (!(cmd = qemuAgentMakeCommand("guest-get-osinfo", NULL)))
         return -1;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0) {
         if (qemuAgentErrorCommandUnsupported(reply))
             return -2;
         return -1;
@@ -2689,8 +2683,7 @@ qemuAgentGetTimezone(qemuAgentPtr mon,
     if (!(cmd = qemuAgentMakeCommand("guest-get-timezone", NULL)))
         return -1;
 
-    if (qemuAgentCommand(mon, cmd, &reply, true,
-                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
+    if (qemuAgentCommand(mon, cmd, &reply, true, mon->timeout) < 0) {
         if (qemuAgentErrorCommandUnsupported(reply))
             return -2;
         return -1;
@@ -2719,3 +2712,16 @@ qemuAgentGetTimezone(qemuAgentPtr mon,
 
     return 0;
 }
+
+/* qemuAgentSetResponseTimeout:
+ * mon: agent monitor
+ * timeout: number of seconds to wait for agent response
+ *
+ * The agent object must be locked prior to calling this function.
+ */
+void
+qemuAgentSetResponseTimeout(qemuAgentPtr mon,
+                            int timeout)
+{
+    mon->timeout = timeout;
+}
index 78e648992a477118dfa2aee426385787aecaf486..85e436cf68d51d692cdbfa90659d54477ae3a69c 100644 (file)
@@ -140,3 +140,6 @@ int qemuAgentGetTimezone(qemuAgentPtr mon,
                          virTypedParameterPtr *params,
                          int *nparams,
                          int *maxparams);
+
+void qemuAgentSetResponseTimeout(qemuAgentPtr mon,
+                                 int timeout);
index ace3761e202369fd0204b844b3f3422dd734b295..e14b414518d9df69f8cf2cd508d08af794e26598 100644 (file)
@@ -2093,6 +2093,8 @@ qemuDomainObjPrivateAlloc(void *opaque)
     if (!(priv->dbusVMStates = virHashCreate(5, dbusVMStateHashFree)))
         goto error;
 
+    /* agent commands block by default, user can choose different behavior */
+    priv->agentTimeout = VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK;
     priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
     priv->driver = opaque;
 
@@ -2875,6 +2877,8 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf,
     if (qemuDomainObjPrivateXMLFormatSlirp(buf, vm) < 0)
         return -1;
 
+    virBufferAsprintf(buf, "<agentTimeout>%i</agentTimeout>\n", priv->agentTimeout);
+
     return 0;
 }
 
@@ -3518,6 +3522,12 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
         goto error;
     }
 
+    if (virXPathInt("string(./agentTimeout)", ctxt, &priv->agentTimeout) == -2) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("failed to parse agent timeout"));
+        goto error;
+    }
+
     if ((node = virXPathNode("./namespaces", ctxt))) {
         xmlNodePtr next;
 
index ab00b257892977682c488f2113085836a021af00..98a9540275b53ae395022b0bcc1661b39c1de154 100644 (file)
@@ -293,6 +293,7 @@ struct _qemuDomainObjPrivate {
     virDomainChrSourceDefPtr monConfig;
     bool monError;
     unsigned long long monStart;
+    int agentTimeout;
 
     qemuAgentPtr agent;
     bool agentError;
index bb75fe5807d5518e7e586bab197178d71b8c32b3..2f06217a5f60be9c2ef27c63a0f785ea61897fd6 100644 (file)
@@ -22685,6 +22685,61 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
     return ret;
 }
 
+
+static int
+qemuDomainAgentSetResponseTimeout(virDomainPtr dom,
+                                  int timeout,
+                                  unsigned int flags)
+{
+    virQEMUDriverPtr driver = dom->conn->privateData;
+    g_autoptr(virQEMUDriverConfig) cfg = NULL;
+    virDomainObjPtr vm = NULL;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    if (timeout < VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("guest agent timeout '%d' is "
+                         "less than the minimum '%d'"),
+                       timeout, VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN);
+        return -1;
+    }
+
+    if (!(vm = qemuDomainObjFromDomain(dom)))
+        return -1;
+
+    cfg = virQEMUDriverGetConfig(driver);
+
+    if (virDomainAgentSetResponseTimeoutEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    /* If domain has an agent, change its timeout. Otherwise just save the
+     * request so that we can set the timeout when the agent appears */
+    if (qemuDomainAgentAvailable(vm, false)) {
+        /* We don't need to acquire a job since we're not interacting with the
+         * agent or the qemu monitor. We're only setting a struct member, so
+         * just acquire the mutex lock. Worst case, any in-process agent
+         * commands will use the newly-set agent timeout. */
+        virObjectLock(QEMU_DOMAIN_PRIVATE(vm)->agent);
+        qemuAgentSetResponseTimeout(QEMU_DOMAIN_PRIVATE(vm)->agent, timeout);
+        virObjectUnlock(QEMU_DOMAIN_PRIVATE(vm)->agent);
+    }
+
+    QEMU_DOMAIN_PRIVATE(vm)->agentTimeout = timeout;
+
+    if (virDomainObjIsActive(vm) &&
+        virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectURIProbe = qemuConnectURIProbe,
@@ -22921,6 +22976,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainCheckpointGetParent = qemuDomainCheckpointGetParent, /* 5.6.0 */
     .domainCheckpointDelete = qemuDomainCheckpointDelete, /* 5.6.0 */
     .domainGetGuestInfo = qemuDomainGetGuestInfo, /* 5.7.0 */
+    .domainAgentSetResponseTimeout = qemuDomainAgentSetResponseTimeout, /* 5.10.0 */
 };
 
 
index 503f49a902f4714696ae6cac53cc414a4475559c..a1384fc655b9dae39cd2a4d2e40b6efa4bef909d 100644 (file)
@@ -8701,6 +8701,7 @@ static virHypervisorDriver hypervisor_driver = {
     .domainCheckpointGetParent = remoteDomainCheckpointGetParent, /* 5.6.0 */
     .domainCheckpointDelete = remoteDomainCheckpointDelete, /* 5.6.0 */
     .domainGetGuestInfo = remoteDomainGetGuestInfo, /* 5.7.0 */
+    .domainAgentSetResponseTimeout = remoteDomainAgentSetResponseTimeout, /* 5.10.0 */
 };
 
 static virNetworkDriver network_driver = {
index f4e3392212012849b3f1c47a43ecffd8199e837f..23e42d17b10247345e9254ca412ffedfe9e856c3 100644 (file)
@@ -3744,6 +3744,16 @@ struct remote_connect_set_identity_args {
     unsigned int flags;
 };
 
+struct remote_domain_agent_set_response_timeout_args {
+    remote_nonnull_domain dom;
+    int timeout;
+    unsigned int flags;
+};
+
+struct remote_domain_agent_set_response_timeout_ret {
+    int result;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -6617,5 +6627,11 @@ enum remote_procedure {
      * @generate: client
      * @acl: connect:write
      */
-    REMOTE_PROC_CONNECT_SET_IDENTITY = 419
+    REMOTE_PROC_CONNECT_SET_IDENTITY = 419,
+
+    /**
+     * @generate: both
+     * @acl: domain:write
+     */
+    REMOTE_PROC_DOMAIN_AGENT_SET_RESPONSE_TIMEOUT = 420
 };
index 51606e7473daee6586eb3af6946f82a53ab493f1..9ad7a857e0791ee3c57b65195c891d50bc3f6661 100644 (file)
@@ -3114,6 +3114,14 @@ struct remote_connect_set_identity_args {
         } params;
         u_int                      flags;
 };
+struct remote_domain_agent_set_response_timeout_args {
+        remote_nonnull_domain      dom;
+        int                        timeout;
+        u_int                      flags;
+};
+struct remote_domain_agent_set_response_timeout_ret {
+        int                        result;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3534,4 +3542,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_CHECKPOINT_DELETE = 417,
         REMOTE_PROC_DOMAIN_GET_GUEST_INFO = 418,
         REMOTE_PROC_CONNECT_SET_IDENTITY = 419,
+        REMOTE_PROC_DOMAIN_AGENT_SET_RESPONSE_TIMEOUT = 420,
 };
index e9031b70874176c4dce69b3100df1424553b60cf..4f6930001efdbf7d3fe7f8bf4524c0fe4a82118f 100644 (file)
       </chains>
     </blockjob>
   </blockjobs>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='4'>
     <name>copy</name>
     <uuid>0439a4a8-db56-4933-9183-d8681d7b0746</uuid>
index 0fba3b69e70e9b79a3f5a71dd6c12db4f01f123a..abd9f6296598c0b5a6c7156a20f5a88867b6e34e 100644 (file)
@@ -23,6 +23,7 @@
   <channelTargetDir path='/tmp/channel'/>
   <allowReboot value='yes'/>
   <blockjobs active='yes'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='qemu' id='1'>
     <name>QEMUGuest1</name>
     <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
index 3d5e8f1438f85527b4afacf1575937919e21f7d5..5d3287606f477372f77f37df80de8ff3aa3e92ad 100644 (file)
   <chardevStdioLogd/>
   <allowReboot value='yes'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='1'>
     <name>upstream</name>
     <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
index 80cc4b4666f5214891a8871b8e745a98e13ed0bd..fdc2d3917307ec71899e70506dcbf70a0db78344 100644 (file)
   <chardevStdioLogd/>
   <allowReboot value='yes'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='1'>
     <name>nest</name>
     <uuid>994cee0d-2a70-4937-9693-0431e39d20f7</uuid>
index 455c30be85f60813ce748bb13e30be0ab1f73926..304fb1b77f84d168b450c880167cba10500af0bb 100644 (file)
   <chardevStdioLogd/>
   <allowReboot value='yes'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='4'>
     <name>upstream</name>
     <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
index 409e97a91887d3b159f3a238712396cb76afa362..d69796e029d619541a885413f648200c485778b3 100644 (file)
   <chardevStdioLogd/>
   <allowReboot value='yes'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='3'>
     <name>upstream</name>
     <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
index 4a660281d2aadbbde837ae1af48ae2dc77b05527..1956eac12031d62e9c439b6867ed0bf846fdae3e 100644 (file)
   <chardevStdioLogd/>
   <allowReboot value='yes'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='7'>
     <name>nest</name>
     <uuid>994cee0d-2a70-4937-9693-0431e39d20f7</uuid>
index 2125b899f4ff5c69f6dbd05c7b4cb4f394901d7f..8a2718293f2a9042329c1fe03700ec98204fbdf1 100644 (file)
   <allowReboot value='yes'/>
   <nodename index='123'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm' id='1'>
     <name>upstream</name>
     <uuid>dcf47dbd-46d1-4d5b-b442-262a806a333a</uuid>
index b8ec650714605784d29aac2b2c344066ce43aa8d..11ec74ecf8822d1c2b6630d9b788a30bcc73037e 100644 (file)
   <channelTargetDir path='/tmp/channel'/>
   <allowReboot value='yes'/>
   <blockjobs active='no'/>
+  <agentTimeout>-2</agentTimeout>
   <domain type='kvm'>
     <name>QEMUGuest1</name>
     <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
index 0feb21ef17760e21b6a27e35f00b04e24bb05d0f..cfdaec1673cf141a4b257a5eac81e5e8e423c809 100644 (file)
@@ -13971,6 +13971,52 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
     return ret;
 }
 
+/*
+ * "guest-agent-timeout" command
+ */
+static const vshCmdInfo info_guest_agent_timeout[] = {
+    {.name = "help",
+     .data = N_("Set the guest agent timeout")
+    },
+    {.name = "desc",
+     .data = N_("Set the number of seconds to wait for a response from the guest agent.")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_guest_agent_timeout[] = {
+    VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+    {.name = "timeout",
+     .type = VSH_OT_INT,
+     .flags = VSH_OFLAG_REQ_OPT,
+     .help = N_("timeout seconds.")
+    },
+    {.name = NULL}
+};
+
+static bool
+cmdGuestAgentTimeout(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom = NULL;
+    int timeout;
+    const unsigned int flags = 0;
+    bool ret = false;
+
+    if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if (vshCommandOptInt(ctl, cmd, "timeout", &timeout) < 0)
+        goto cleanup;
+
+    if (virDomainAgentSetResponseTimeout(dom, timeout, flags) < 0)
+        goto cleanup;
+
+    ret = true;
+ cleanup:
+    virshDomainFree(dom);
+    return ret;
+}
+
 /*
  * "guestinfo" command
  */
@@ -14492,6 +14538,12 @@ const vshCmdDef domManagementCmds[] = {
      .info = info_qemu_agent_command,
      .flags = 0
     },
+    {.name = "guest-agent-timeout",
+     .handler = cmdGuestAgentTimeout,
+     .opts = opts_guest_agent_timeout,
+     .info = info_guest_agent_timeout,
+     .flags = 0
+    },
     {.name = "reboot",
      .handler = cmdReboot,
      .opts = opts_reboot,
index cf2798e71aa5509d5fa1f0ad942326cdae03c924..c261d403d88fe3e3d52673eb5b87b6fba4854006 100644 (file)
@@ -1820,6 +1820,17 @@ events until a timeout or interrupt key.
 When I<--timestamp> is used, a human-readable timestamp will be printed
 before the event.
 
+=item B<guest-agent-timeout> I<domain> I<--timeout> B<value>
+
+Set how long to wait for a response from guest agent commands. By default,
+agent commands block forever waiting for a response. B<value> must be a
+positive value (wait for given amount of seconds) or one of the following
+values:
+
+ -2 - block forever waiting for a resuly,
+ -1 - reset timeout to the default value,
+  0 - do not wait at all,
+
 =item B<guestinfo> I<domain> [I<--user>] [I<--os>] [I<--timezone>]
 [I<--hostname>] [I<--filesystem>]