virsh: await: Introduce 'guest-agent-available' condition

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@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa
2025-06-12 10:17:03 +02:00
parent 05c9f3752d
commit 6a8fb1851d
2 changed files with 47 additions and 0 deletions
+5
View File
@@ -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
+42
View File
@@ -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,
},
};