From: Peter Krempa <pkrempa(a)redhat.com>
The new condition allows waiting for the guest agent to show up, which
usually means that the guest has booted enough to respond to external
stimuli.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
docs/manpages/virsh.rst | 5 +++++
tools/virsh-domain-event.c | 42 ++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 1515f84063..0259c21065 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -3080,6 +3080,11 @@ Supported conditions:
domain is or becomes inactive
+ *guest-agent-available*
+
+ the guest agent inside the guest connects and becomes available for commands
+ (usually means that the guest has booted)
+
If *--timeout* is specified, the command gives up waiting for the condition to
satisfy after *seconds* have elapsed. If SIGINT is delivered to virsh
(usually via ``Ctrl-C``) the wait is given up immediately. In non-interactive
diff --git a/tools/virsh-domain-event.c b/tools/virsh-domain-event.c
index 2cd52933c7..de33ed9d74 100644
--- a/tools/virsh-domain-event.c
+++ b/tools/virsh-domain-event.c
@@ -24,6 +24,7 @@
#include "virenum.h"
#include "virtime.h"
#include "virtypedparam.h"
+#include "virxml.h"
/*
* "event" command
@@ -1109,6 +1110,20 @@ virshDomainEventAwaitCallbackLifecycle(virConnectPtr conn
G_GNUC_UNUSED,
}
+static void
+virshDomainEventAwaitAgentLifecycle(virConnectPtr conn G_GNUC_UNUSED,
+ virDomainPtr dom G_GNUC_UNUSED,
+ int state G_GNUC_UNUSED,
+ int reason G_GNUC_UNUSED,
+ void *opaque G_GNUC_UNUSED)
+{
+ struct virshDomEventAwaitConditionData *data = opaque;
+
+ if (data->cond->handler(data) < 1)
+ vshEventDone(data->ctl);
+}
+
+
struct virshDomainEventAwaitCallbackTuple {
int event;
virConnectDomainEventGenericCallback eventCB;
@@ -1120,6 +1135,9 @@ static const struct virshDomainEventAwaitCallbackTuple callbacks[]
=
{ .event = VIR_DOMAIN_EVENT_ID_LIFECYCLE,
.eventCB = VIR_DOMAIN_EVENT_CALLBACK(virshDomainEventAwaitCallbackLifecycle),
},
+ { .event = VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE,
+ .eventCB = VIR_DOMAIN_EVENT_CALLBACK(virshDomainEventAwaitAgentLifecycle),
+ },
};
@@ -1152,11 +1170,35 @@ virshDomainEventAwaitConditionDomainInactive(struct
virshDomEventAwaitConditionD
}
+static int
+virshDomainEventAwaitConditionGuestAgentAvailable(struct virshDomEventAwaitConditionData
*data)
+{
+ g_autoptr(xmlDoc) xml = NULL;
+ g_autoptr(xmlXPathContext) ctxt = NULL;
+ g_autofree char *state = NULL;
+
+ if (virshDomainGetXMLFromDom(data->ctl, data->dom, 0, &xml, &ctxt) <
0)
+ return -1;
+
+ if ((state = virXPathString("string(//devices/channel/target[@name =
'org.qemu.guest_agent.0']/@state)",
+ ctxt))) {
+ if (STREQ(state, "connected"))
+ return 0;
+ }
+
+ return 1;
+}
+
+
static const struct virshDomainEventAwaitCondition conditions[] = {
{ .name = "domain-inactive",
.event = VIR_DOMAIN_EVENT_ID_LIFECYCLE,
.handler = virshDomainEventAwaitConditionDomainInactive,
},
+ { .name = "guest-agent-available",
+ .event = VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE,
+ .handler = virshDomainEventAwaitConditionGuestAgentAvailable,
+ },
};
--
2.49.0