Implementation is pretty similar to the one found in the qemu driver. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- src/bhyve/bhyve_driver.c | 192 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index a0d97d3f86..d72b97c7ac 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -2807,6 +2807,197 @@ bhyveDomainRename(virDomainPtr domain, return ret; } +static const unsigned int bhyveDomainGetGuestInfoSupportedTypes = + VIR_DOMAIN_GUEST_INFO_USERS | + VIR_DOMAIN_GUEST_INFO_OS | + VIR_DOMAIN_GUEST_INFO_TIMEZONE | + VIR_DOMAIN_GUEST_INFO_HOSTNAME | + VIR_DOMAIN_GUEST_INFO_FILESYSTEM | + VIR_DOMAIN_GUEST_INFO_DISKS | + VIR_DOMAIN_GUEST_INFO_INTERFACES | + VIR_DOMAIN_GUEST_INFO_LOAD; + +static int +bhyveDomainGetGuestInfoCheckSupport(unsigned int types, + unsigned int *supportedTypes) +{ + if (types == 0) { + *supportedTypes = bhyveDomainGetGuestInfoSupportedTypes; + return 0; + } + + *supportedTypes = types & bhyveDomainGetGuestInfoSupportedTypes; + + if (types != *supportedTypes) { + virReportError(VIR_ERR_INVALID_ARG, + _("unsupported guest information types '0x%1$x'"), + types & ~bhyveDomainGetGuestInfoSupportedTypes); + return -1; + } + + return 0; +} + + +static int +bhyveDomainGetGuestInfo(virDomainPtr domain, + unsigned int types, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + virDomainObj *vm = NULL; + qemuAgent *agent = NULL; + int ret = -1; + g_autofree char *hostname = NULL; + unsigned int supportedTypes; + bool report_unsupported = types != 0; + int rc; + size_t nfs = 0; + qemuAgentFSInfo **agentfsinfo = NULL; + size_t ndisks = 0; + qemuAgentDiskInfo **agentdiskinfo = NULL; + virDomainInterfacePtr *ifaces = NULL; + size_t nifaces = 0; + double load1m = 0; + double load5m = 0; + double load15m = 0; + bool format_load = false; + size_t i; + g_autoptr(virTypedParamList) list = virTypedParamListNew(); + + if (bhyveDomainGetGuestInfoCheckSupport(types, &supportedTypes) < 0) + return -1; + + virCheckFlags(0, -1); + + if (!(vm = bhyveDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainGetGuestInfoEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjBeginAgentJob(vm, VIR_AGENT_JOB_QUERY) < 0) + goto cleanup; + + if (bhyveDomainEnsureAgent(vm, true) < 0) + goto endagentjob; + + agent = bhyveDomainObjEnterAgent(vm); + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_USERS && + qemuAgentGetUsers(agent, list, report_unsupported) == -1) + goto exitagent; + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_OS && + qemuAgentGetOSInfo(agent, list, report_unsupported) == -1) + goto exitagent; + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_TIMEZONE && + qemuAgentGetTimezone(agent, list, report_unsupported) == -1) + goto exitagent; + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_HOSTNAME && + qemuAgentGetHostname(agent, &hostname, report_unsupported) == -1) + goto exitagent; + + if (hostname) + virTypedParamListAddString(list, hostname, + VIR_DOMAIN_GUEST_INFO_HOSTNAME_HOSTNAME); + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_FILESYSTEM) { + rc = qemuAgentGetFSInfo(agent, &agentfsinfo, report_unsupported); + if (rc == -1) + goto exitagent; + if (rc >= 0) + nfs = rc; + } + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_DISKS) { + rc = qemuAgentGetDisks(agent, &agentdiskinfo, report_unsupported); + if (rc == -1) + goto exitagent; + if (rc >= 0) + ndisks = rc; + } + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_INTERFACES) { + rc = qemuAgentGetInterfaces(agent, &ifaces, report_unsupported); + if (rc == -1) + goto exitagent; + if (rc >= 0) + nifaces = rc; + } + + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_LOAD) { + rc = qemuAgentGetLoadAvg(agent, &load1m, &load5m, &load15m, report_unsupported); + if (rc == -1) + goto exitagent; + if (rc >= 0) + format_load = true; + } + + bhyveDomainObjExitAgent(vm, agent); + virDomainObjEndAgentJob(vm); + + if (nfs > 0 || ndisks > 0) { + if (virDomainObjBeginJob(vm, VIR_JOB_QUERY) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + + /* we need to convert the agent fsinfo struct to parameters and match + * it to the vm disk target */ + if (nfs > 0) + qemuAgentFSInfoFormatParams(agentfsinfo, nfs, vm->def, list); + + if (ndisks > 0) + qemuAgentDiskInfoFormatParams(agentdiskinfo, ndisks, vm->def, list); + + endjob: + virDomainObjEndJob(vm); + } + + if (nifaces > 0) { + qemuAgentInterfaceFormatParams(ifaces, nifaces, list); + } + + if (format_load) { + virTypedParamListAddDouble(list, load1m, VIR_DOMAIN_GUEST_INFO_LOAD_1M); + virTypedParamListAddDouble(list, load5m, VIR_DOMAIN_GUEST_INFO_LOAD_5M); + virTypedParamListAddDouble(list, load15m, VIR_DOMAIN_GUEST_INFO_LOAD_15M); + } + + if (virTypedParamListSteal(list, params, nparams) < 0) + goto cleanup; + + ret = 0; + + cleanup: + for (i = 0; i < nfs; i++) + qemuAgentFSInfoFree(agentfsinfo[i]); + g_free(agentfsinfo); + for (i = 0; i < ndisks; i++) + qemuAgentDiskInfoFree(agentdiskinfo[i]); + g_free(agentdiskinfo); + if (ifaces && nifaces > 0) { + for (i = 0; i < nifaces; i++) + virDomainInterfaceFree(ifaces[i]); + } + g_free(ifaces); + + virDomainObjEndAPI(&vm); + return ret; + + exitagent: + bhyveDomainObjExitAgent(vm, agent); + + endagentjob: + virDomainObjEndAgentJob(vm); + goto cleanup; +} + static virHypervisorDriver bhyveHypervisorDriver = { .name = "bhyve", .connectURIProbe = bhyveConnectURIProbe, @@ -2885,6 +3076,7 @@ static virHypervisorDriver bhyveHypervisorDriver = { .domainAuthorizedSSHKeysGet = bhyveDomainAuthorizedSSHKeysGet, /* 12.6.0 */ .domainAuthorizedSSHKeysSet = bhyveDomainAuthorizedSSHKeysSet, /* 12.6.0 */ .domainRename = bhyveDomainRename, /* 12.6.0 */ + .domainGetGuestInfo = bhyveDomainGetGuestInfo, /* 12.7.0 */ }; -- 2.52.0