[PATCH 0/2] bhyve: add agent support
Roman Bogorodskiy (2): qemu: move qemu_agent.c to hypervisor/ bhyve: add agent support po/POTFILES | 2 +- src/bhyve/bhyve_domain.c | 32 +++++ src/bhyve/bhyve_domain.h | 14 ++ src/bhyve/bhyve_driver.c | 180 +++++++++++++++++++++++++- src/bhyve/bhyve_process.c | 118 +++++++++++++++++ src/bhyve/bhyve_process.h | 4 + src/hypervisor/meson.build | 1 + src/{qemu => hypervisor}/qemu_agent.c | 20 ++- src/{qemu => hypervisor}/qemu_agent.h | 3 +- src/libvirt_private.syms | 32 +++++ src/qemu/meson.build | 1 - src/qemu/qemu_process.c | 3 +- tests/qemuagenttest.c | 2 +- tests/qemumonitortestutils.c | 6 +- tests/qemumonitortestutils.h | 2 +- 15 files changed, 405 insertions(+), 15 deletions(-) rename src/{qemu => hypervisor}/qemu_agent.c (99%) rename src/{qemu => hypervisor}/qemu_agent.h (98%) -- 2.52.0
To prepare for the qemu agent support for the bhyve driver, move the implementation from qemu/ to hypervisor. This way this implementation can be shared across multiple drivers. The move is mostly mechanical except qemuAgentOpen() which now accepts the "timeout" argument for the agent timeout. As the original code used QEMU_DOMAIN_PRIVATE() to access the agent timeout value, this change allows to make the code driver-independent. emuAgentOpenUnix() is wrapped with #ifndef WIN32 so it does not fail on mingw. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- po/POTFILES | 2 +- src/hypervisor/meson.build | 1 + src/{qemu => hypervisor}/qemu_agent.c | 20 +++++++++++++---- src/{qemu => hypervisor}/qemu_agent.h | 3 ++- src/libvirt_private.syms | 32 +++++++++++++++++++++++++++ src/qemu/meson.build | 1 - src/qemu/qemu_process.c | 3 ++- tests/qemuagenttest.c | 2 +- tests/qemumonitortestutils.c | 6 +++-- tests/qemumonitortestutils.h | 2 +- 10 files changed, 60 insertions(+), 12 deletions(-) rename src/{qemu => hypervisor}/qemu_agent.c (99%) rename src/{qemu => hypervisor}/qemu_agent.h (98%) diff --git a/po/POTFILES b/po/POTFILES index a5f8705eb8..3d52f23002 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -100,6 +100,7 @@ src/hypervisor/domain_cgroup.c src/hypervisor/domain_driver.c src/hypervisor/domain_logcontext.c src/hypervisor/domain_interface.c +src/hypervisor/qemu_agent.c src/hypervisor/virhostdev.c src/interface/interface_backend_netcf.c src/interface/interface_backend_udev.c @@ -166,7 +167,6 @@ src/nwfilter/nwfilter_tech_driver.c src/openvz/openvz_conf.c src/openvz/openvz_driver.c src/openvz/openvz_util.c -src/qemu/qemu_agent.c src/qemu/qemu_alias.c src/qemu/qemu_backup.c src/qemu/qemu_block.c diff --git a/src/hypervisor/meson.build b/src/hypervisor/meson.build index 91eaefbebc..90055b950e 100644 --- a/src/hypervisor/meson.build +++ b/src/hypervisor/meson.build @@ -2,6 +2,7 @@ hypervisor_sources = [ 'domain_cgroup.c', 'domain_driver.c', 'domain_interface.c', + 'qemu_agent.c', 'virclosecallbacks.c', 'virhostdev.c', ] diff --git a/src/qemu/qemu_agent.c b/src/hypervisor/qemu_agent.c similarity index 99% rename from src/qemu/qemu_agent.c rename to src/hypervisor/qemu_agent.c index ee0921eca6..70f0cde5dd 100644 --- a/src/qemu/qemu_agent.c +++ b/src/hypervisor/qemu_agent.c @@ -21,14 +21,15 @@ #include <config.h> -#include <poll.h> +#ifndef WIN32 +# include <poll.h> +#endif #include <unistd.h> #include <fcntl.h> #include <sys/time.h> #include <gio/gio.h> #include "qemu_agent.h" -#include "qemu_domain.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" @@ -146,6 +147,7 @@ static void qemuAgentDispose(void *obj) virResetError(&agent->lastError); } +#ifndef WIN32 static int qemuAgentOpenUnix(const char *socketpath) { @@ -183,6 +185,15 @@ qemuAgentOpenUnix(const char *socketpath) VIR_FORCE_CLOSE(agentfd); return -1; } +#else /* WIN32 */ +static int +qemuAgentOpenUnix(const char *socketpath G_GNUC_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Opening UNIX sockets is not supported on Win32 platform")); + return -1; +} +#endif /* WIN32 */ static int @@ -584,7 +595,8 @@ qemuAgent * qemuAgentOpen(virDomainObj *vm, const virDomainChrSourceDef *config, GMainContext *context, - qemuAgentCallbacks *cb) + qemuAgentCallbacks *cb, + int timeout) { qemuAgent *agent; g_autoptr(GError) gerr = NULL; @@ -601,7 +613,7 @@ qemuAgentOpen(virDomainObj *vm, if (!(agent = virObjectLockableNew(qemuAgentClass))) return NULL; - agent->timeout = QEMU_DOMAIN_PRIVATE(vm)->agentTimeout; + agent->timeout = timeout; agent->fd = -1; if (virCondInit(&agent->notify) < 0) { virReportSystemError(errno, "%s", diff --git a/src/qemu/qemu_agent.h b/src/hypervisor/qemu_agent.h similarity index 98% rename from src/qemu/qemu_agent.h rename to src/hypervisor/qemu_agent.h index 860f19b6bd..9117d3743c 100644 --- a/src/qemu/qemu_agent.h +++ b/src/hypervisor/qemu_agent.h @@ -38,7 +38,8 @@ struct _qemuAgentCallbacks { qemuAgent *qemuAgentOpen(virDomainObj *vm, const virDomainChrSourceDef *config, GMainContext *context, - qemuAgentCallbacks *cb); + qemuAgentCallbacks *cb, + int timeout); void qemuAgentClose(qemuAgent *mon); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cf0e71cc6a..3af6cc568a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1705,6 +1705,38 @@ virDomainInterfaceStopDevice; virDomainInterfaceStopDevices; virDomainInterfaceVportRemove; +# hypervisor/qemu_agent.h +qemuAgentArbitraryCommand; +qemuAgentClose; +qemuAgentDiskInfoFree; +qemuAgentFSFreeze; +qemuAgentFSInfoFree; +qemuAgentFSThaw; +qemuAgentFSTrim; +qemuAgentGetDisks; +qemuAgentGetFSInfo; +qemuAgentGetHostname; +qemuAgentGetInterfaces; +qemuAgentGetLoadAvg; +qemuAgentGetOSInfo; +qemuAgentGetTime; +qemuAgentGetTimezone; +qemuAgentGetUsers; +qemuAgentGetVCPUs; +qemuAgentNotifyClose; +qemuAgentNotifyEvent; +qemuAgentOpen; +qemuAgentSetResponseTimeout; +qemuAgentSetTime; +qemuAgentSetUserPassword; +qemuAgentSetVCPUs; +qemuAgentShutdown; +qemuAgentSSHAddAuthorizedKeys; +qemuAgentSSHGetAuthorizedKeys; +qemuAgentSSHRemoveAuthorizedKeys; +qemuAgentSuspend; +qemuAgentUpdateCPUInfo; + # hypervisor/virclosecallbacks.h virCloseCallbacksDomainAdd; virCloseCallbacksDomainAlloc; diff --git a/src/qemu/meson.build b/src/qemu/meson.build index b4fb62f14f..2615a5ceef 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -1,5 +1,4 @@ qemu_driver_sources = [ - 'qemu_agent.c', 'qemu_alias.c', 'qemu_backup.c', 'qemu_block.c', diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a6d33f6746..83f5ebb19c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -236,7 +236,8 @@ qemuConnectAgent(virQEMUDriver *driver, virDomainObj *vm) agent = qemuAgentOpen(vm, config->source, virEventThreadGetContext(priv->eventThread), - &agentCallbacks); + &agentCallbacks, + QEMU_DOMAIN_PRIVATE(vm)->agentTimeout); if (!virDomainObjIsActive(vm)) { qemuAgentClose(agent); diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c index 9c64ed3c5f..74cd317e74 100644 --- a/tests/qemuagenttest.c +++ b/tests/qemuagenttest.c @@ -23,7 +23,7 @@ #include "testutilsqemu.h" #include "qemumonitortestutils.h" #include "qemu/qemu_conf.h" -#include "qemu/qemu_agent.h" +#include "hypervisor/qemu_agent.h" #include "virerror.h" diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index 88a369188e..b6e17fc2ca 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -27,9 +27,10 @@ #include "virthread.h" #define LIBVIRT_QEMU_PROCESSPRIV_H_ALLOW +#include "hypervisor/qemu_agent.h" +#include "qemu/qemu_domain.h" #include "qemu/qemu_processpriv.h" #include "qemu/qemu_monitor.h" -#include "qemu/qemu_agent.h" #include "rpc/virnetsocket.h" #include "viralloc.h" #include "virlog.h" @@ -1201,7 +1202,8 @@ qemuMonitorTestNewAgent(virDomainXMLOption *xmlopt) if (!(test->agent = qemuAgentOpen(test->vm, &src, virEventThreadGetContext(test->eventThread), - &qemuMonitorTestAgentCallbacks))) + &qemuMonitorTestAgentCallbacks, + QEMU_DOMAIN_PRIVATE(test->vm)->agentTimeout))) goto error; virObjectLock(test->agent); diff --git a/tests/qemumonitortestutils.h b/tests/qemumonitortestutils.h index 6d26526f60..4f136410ee 100644 --- a/tests/qemumonitortestutils.h +++ b/tests/qemumonitortestutils.h @@ -21,7 +21,7 @@ #include "qemu/qemu_conf.h" #include "qemu/qemu_monitor.h" -#include "qemu/qemu_agent.h" +#include "hypervisor/qemu_agent.h" typedef struct _qemuMonitorTest qemuMonitorTest; -- 2.52.0
On 5/14/26 07:02, Roman Bogorodskiy wrote:
To prepare for the qemu agent support for the bhyve driver, move the implementation from qemu/ to hypervisor. This way this implementation can be shared across multiple drivers.
The move is mostly mechanical except qemuAgentOpen() which now accepts the "timeout" argument for the agent timeout. As the original code used QEMU_DOMAIN_PRIVATE() to access the agent timeout value, this change allows to make the code driver-independent.
emuAgentOpenUnix() is wrapped with #ifndef WIN32 so it does not fail on
qemuAgentOpenUnix()
mingw.
Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
Michal
Implement QEMU Guest Agent support for bhyve. In bhyve it can configured using the virtio-console device. This change covers only two APIs using the agent: - DomainQemuAgentCommand -- the most generic one. - DomainGetHostname -- extended to support not only DHCP lease source, but an agent as well. It shares the qemu agent implementation with the qemu driver. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- src/bhyve/bhyve_domain.c | 32 +++++++ src/bhyve/bhyve_domain.h | 14 +++ src/bhyve/bhyve_driver.c | 180 +++++++++++++++++++++++++++++++++++++- src/bhyve/bhyve_process.c | 118 +++++++++++++++++++++++++ src/bhyve/bhyve_process.h | 4 + 5 files changed, 345 insertions(+), 3 deletions(-) diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c index 832a9b58d1..6367985efc 100644 --- a/src/bhyve/bhyve_domain.c +++ b/src/bhyve/bhyve_domain.c @@ -41,6 +41,7 @@ bhyveDomainObjPrivateAlloc(void *opaque) { bhyveDomainObjPrivate *priv = g_new0(bhyveDomainObjPrivate, 1); + priv->agentTimeout = 30; priv->driver = opaque; return priv; @@ -663,3 +664,34 @@ virXMLNamespace virBhyveDriverDomainXMLNamespace = { .uri = "http://libvirt.org/schemas/domain/bhyve/1.0", }; + + +int +virBhyveDomainObjStartWorker(virDomainObj *dom) +{ + bhyveDomainObjPrivate *priv = dom->privateData; + + if (!priv->eventThread) { + g_autofree char *threadName = g_strdup_printf("vm-%s", dom->def->name); + if (!(priv->eventThread = virEventThreadNew(threadName))) + return -1; + } + + return 0; +} + + +void +virBhyveDomainObjStopWorker(virDomainObj *dom) +{ + bhyveDomainObjPrivate *priv = dom->privateData; + virEventThread *eventThread; + + if (!priv->eventThread) + return; + + eventThread = g_steal_pointer(&priv->eventThread); + virObjectUnlock(dom); + g_object_unref(eventThread); + virObjectLock(dom); +} diff --git a/src/bhyve/bhyve_domain.h b/src/bhyve/bhyve_domain.h index 5a539bc4c0..888ef2f84b 100644 --- a/src/bhyve/bhyve_domain.h +++ b/src/bhyve/bhyve_domain.h @@ -22,6 +22,8 @@ #include "domain_addr.h" #include "domain_conf.h" +#include "vireventthread.h" +#include "hypervisor/qemu_agent.h" #include "bhyve_monitor.h" @@ -33,10 +35,22 @@ struct _bhyveDomainObjPrivate { bool persistentAddrs; bhyveMonitor *mon; + + qemuAgent *agent; + bool agentError; + int agentTimeout; + + virEventThread *eventThread; }; +#define BHYVE_DOMAIN_PRIVATE(vm) \ + ((bhyveDomainObjPrivate *) (vm)->privateData) + virDomainXMLOption *virBhyveDriverCreateXMLConf(struct _bhyveConn *); extern virDomainXMLPrivateDataCallbacks virBhyveDriverPrivateDataCallbacks; extern virDomainDefParserConfig virBhyveDriverDomainDefParserConfig; extern virXMLNamespace virBhyveDriverDomainXMLNamespace; + +int virBhyveDomainObjStartWorker(virDomainObj *dom); +void virBhyveDomainObjStopWorker(virDomainObj *dom); diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index c8dd1a728a..7103be67a0 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -53,6 +53,7 @@ #include "virstring.h" #include "cpu/cpu.h" #include "viraccessapicheck.h" +#include "viraccessapicheckqemu.h" #include "virhostcpu.h" #include "virhostmem.h" #include "virportallocator.h" @@ -1895,6 +1896,165 @@ bhyveDomainInterfaceAddresses(virDomainPtr domain, } +static qemuAgent * +bhyveDomainObjEnterAgent(virDomainObj *obj) +{ + bhyveDomainObjPrivate *priv = obj->privateData; + qemuAgent *agent = priv->agent; + + VIR_DEBUG("Entering agent (agent=%p vm=%p name=%s)", + priv->agent, obj, obj->def->name); + + virObjectLock(agent); + virObjectRef(agent); + virObjectUnlock(obj); + + return agent; +} + + +static void +bhyveDomainObjExitAgent(virDomainObj *obj, qemuAgent *agent) +{ + virObjectUnlock(agent); + virObjectUnref(agent); + virObjectLock(obj); + + VIR_DEBUG("Exited agent (agent=%p vm=%p name=%s)", + agent, obj, obj->def->name); +} + + +static bool +bhyveDomainAgentAvailable(virDomainObj *vm, + bool reportError) +{ + bhyveDomainObjPrivate *priv = vm->privateData; + + if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) { + if (reportError) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain is not running")); + } + return false; + } + + if (!priv->agent) { + if (bhyveFindAgentConfig(vm->def)) { + if (reportError) { + virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s", + _("QEMU guest agent is not connected")); + } + return false; + } else { + if (reportError) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("QEMU guest agent is not configured")); + } + return false; + } + } + return true; +} + + +static int +bhyveDomainEnsureAgent(virDomainObj *vm, + bool reportError) +{ + bhyveDomainObjPrivate *priv = vm->privateData; + + if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) { + if (reportError) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain is not running")); + } + return -1; + } + + if (priv->agent) + return 0; + + if (!priv->eventThread && + virBhyveDomainObjStartWorker(vm) < 0) + return -1; + + if (bhyveConnectAgent(NULL, vm) < 0) + return -1; + + return 0; +} + + +static int +bhyveDomainGetHostnameAgent(virDomainObj *vm, + char **hostname) +{ + qemuAgent *agent; + int ret = -1; + + if (virDomainObjBeginAgentJob(vm, VIR_AGENT_JOB_QUERY) < 0) + return -1; + + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + + if (bhyveDomainEnsureAgent(vm, true) < 0) + goto endjob; + + agent = bhyveDomainObjEnterAgent(vm); + ret = qemuAgentGetHostname(agent, hostname, true); + bhyveDomainObjExitAgent(vm, agent); + + endjob: + virDomainObjEndAgentJob(vm); + return ret; +} + + +static char * +bhyveDomainQemuAgentCommand(virDomainPtr domain, + const char *cmd, + int timeout, + unsigned int flags) +{ + virDomainObj *vm; + int ret = -1; + char *result = NULL; + qemuAgent *agent; + + virCheckFlags(0, NULL); + + if (!(vm = bhyveDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainQemuAgentCommandEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjBeginAgentJob(vm, VIR_AGENT_JOB_MODIFY) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + + if (!bhyveDomainAgentAvailable(vm, true)) + goto endjob; + + agent = bhyveDomainObjEnterAgent(vm); + ret = qemuAgentArbitraryCommand(agent, cmd, &result, timeout); + bhyveDomainObjExitAgent(vm, agent); + if (ret < 0) + VIR_FREE(result); + + endjob: + virDomainObjEndAgentJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + return result; +} + + static int bhyveDomainGetHostnameLease(virDomainObj *vm, char **hostname) @@ -1961,7 +2121,15 @@ bhyveDomainGetHostname(virDomainPtr domain, virDomainObj *vm = NULL; char *hostname = NULL; - virCheckFlags(VIR_DOMAIN_GET_HOSTNAME_LEASE, NULL); + virCheckFlags(VIR_DOMAIN_GET_HOSTNAME_LEASE | + VIR_DOMAIN_GET_HOSTNAME_AGENT, NULL); + + VIR_EXCLUSIVE_FLAGS_RET(VIR_DOMAIN_GET_HOSTNAME_LEASE, + VIR_DOMAIN_GET_HOSTNAME_AGENT, + NULL); + + if (!(flags & VIR_DOMAIN_GET_HOSTNAME_AGENT)) + flags |= VIR_DOMAIN_GET_HOSTNAME_LEASE; if (!(vm = bhyveDomObjFromDomain(domain))) return NULL; @@ -1969,8 +2137,13 @@ bhyveDomainGetHostname(virDomainPtr domain, if (virDomainGetHostnameEnsureACL(domain->conn, vm->def) < 0) goto cleanup; - if (bhyveDomainGetHostnameLease(vm, &hostname) < 0) - goto cleanup; + if (flags & VIR_DOMAIN_GET_HOSTNAME_LEASE) { + if (bhyveDomainGetHostnameLease(vm, &hostname) < 0) + goto cleanup; + } else if (flags & VIR_DOMAIN_GET_HOSTNAME_AGENT) { + if (bhyveDomainGetHostnameAgent(vm, &hostname) < 0) + goto cleanup; + } if (!hostname) { virReportError(VIR_ERR_NO_HOSTNAME, @@ -2052,6 +2225,7 @@ static virHypervisorDriver bhyveHypervisorDriver = { .domainGetVcpuPinInfo = bhyveDomainGetVcpuPinInfo, /* 12.1.0 */ .domainInterfaceAddresses = bhyveDomainInterfaceAddresses, /* 12.3.0 */ .domainGetHostname = bhyveDomainGetHostname, /* 12.3.0 */ + .domainQemuAgentCommand = bhyveDomainQemuAgentCommand, /* 12.4.0 */ }; diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c index 6078d995cd..7652a998e5 100644 --- a/src/bhyve/bhyve_process.c +++ b/src/bhyve/bhyve_process.c @@ -171,6 +171,118 @@ bhyveSetResourceLimits(struct _bhyveConn *driver, virDomainObj *vm) return 0; } +virDomainChrDef * +bhyveFindAgentConfig(virDomainDef *def) +{ + size_t i; + + for (i = 0; i < def->nchannels; i++) { + virDomainChrDef *channel = def->channels[i]; + + if (channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) + continue; + + + if (STREQ_NULLABLE(channel->target.name, "org.qemu.guest_agent.0")) { + return channel; + } + } + + return NULL; +} + +static void +bhyveProcessHandleAgentEOF(qemuAgent *agent, + virDomainObj *vm) +{ + bhyveDomainObjPrivate *priv; + + virObjectLock(vm); + VIR_INFO("Received EOF from agent on %p '%s'", vm, vm->def->name); + + priv = vm->privateData; + + if (!priv->agent) { + VIR_DEBUG("Agent freed already"); + goto unlock; + } + + qemuAgentClose(agent); + priv->agent = NULL; + priv->agentError = false; + + virObjectUnlock(vm); + return; + + unlock: + virObjectUnlock(vm); + return; +} + +/* + * This is invoked when there is some kind of error + * parsing data to/from the agent. The VM can continue + * to run, but no further agent commands will be + * allowed + */ +static void +bhyveProcessHandleAgentError(qemuAgent *agent G_GNUC_UNUSED, + virDomainObj *vm) +{ + bhyveDomainObjPrivate *priv; + + virObjectLock(vm); + VIR_INFO("Received error from agent on %p '%s'", vm, vm->def->name); + + priv = vm->privateData; + + priv->agentError = true; + + virObjectUnlock(vm); +} + +static qemuAgentCallbacks agentCallbacks = { + .eofNotify = bhyveProcessHandleAgentEOF, + .errorNotify = bhyveProcessHandleAgentError, +}; + +int +bhyveConnectAgent(struct _bhyveConn *driver G_GNUC_UNUSED, virDomainObj *vm) +{ + bhyveDomainObjPrivate *priv = vm->privateData; + qemuAgent *agent = NULL; + virDomainChrDef *config = bhyveFindAgentConfig(vm->def); + + if (!config) + return 0; + + if (priv->agent) + return 0; + + agent = qemuAgentOpen(vm, + config->source, + virEventThreadGetContext(priv->eventThread), + &agentCallbacks, + BHYVE_DOMAIN_PRIVATE(vm)->agentTimeout); + + if (!virDomainObjIsActive(vm)) { + qemuAgentClose(agent); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest crashed while connecting to the guest agent")); + return -1; + } + + priv->agent = agent; + if (!priv->agent) { + VIR_WARN("Cannot connect to QEMU guest agent for %s", vm->def->name); + priv->agentError = true; + virResetLastError(); + } + + return 0; +} + + static int virBhyveProcessStartImpl(struct _bhyveConn *driver, virDomainObj *vm, @@ -293,6 +405,9 @@ virBhyveProcessStartImpl(struct _bhyveConn *driver, virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); priv->mon = bhyveMonitorOpen(vm, driver); + if (virBhyveDomainObjStartWorker(vm) < 0) + goto cleanup; + if (virDomainObjSave(vm, driver->xmlopt, BHYVE_STATE_DIR) < 0) goto cleanup; @@ -714,6 +829,9 @@ virBhyveProcessReconnect(virDomainObj *vm, virDomainNetNotifyActualDevice(conn, vm->def, net); } + if (virBhyveDomainObjStartWorker(vm) < 0) + goto cleanup; + cleanup: if (ret < 0) { /* If VM is reported to be in active state, but we cannot find diff --git a/src/bhyve/bhyve_process.h b/src/bhyve/bhyve_process.h index 5e0acc810c..bf82f748a6 100644 --- a/src/bhyve/bhyve_process.h +++ b/src/bhyve/bhyve_process.h @@ -56,6 +56,10 @@ int virBhyveGetDomainTotalCpuStats(virDomainObj *vm, void virBhyveProcessReconnectAll(struct _bhyveConn *driver); +int bhyveConnectAgent(struct _bhyveConn *driver, virDomainObj *vm); + +virDomainChrDef *bhyveFindAgentConfig(virDomainDef *def); + typedef enum { VIR_BHYVE_PROCESS_START_AUTODESTROY = 1 << 0, } bhyveProcessStartFlags; -- 2.52.0
On 5/14/26 07:02, Roman Bogorodskiy wrote:
Roman Bogorodskiy (2): qemu: move qemu_agent.c to hypervisor/ bhyve: add agent support
po/POTFILES | 2 +- src/bhyve/bhyve_domain.c | 32 +++++ src/bhyve/bhyve_domain.h | 14 ++ src/bhyve/bhyve_driver.c | 180 +++++++++++++++++++++++++- src/bhyve/bhyve_process.c | 118 +++++++++++++++++ src/bhyve/bhyve_process.h | 4 + src/hypervisor/meson.build | 1 + src/{qemu => hypervisor}/qemu_agent.c | 20 ++- src/{qemu => hypervisor}/qemu_agent.h | 3 +- src/libvirt_private.syms | 32 +++++ src/qemu/meson.build | 1 - src/qemu/qemu_process.c | 3 +- tests/qemuagenttest.c | 2 +- tests/qemumonitortestutils.c | 6 +- tests/qemumonitortestutils.h | 2 +- 15 files changed, 405 insertions(+), 15 deletions(-) rename src/{qemu => hypervisor}/qemu_agent.c (99%) rename src/{qemu => hypervisor}/qemu_agent.h (98%)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Micahl
participants (2)
-
Michal Prívozník -
Roman Bogorodskiy