[libvirt PATCH v4 0/5] add interface infomation in guestinfo command

zhanglei (5): domain: add interface information to 'virDomainGetGuestInfo' virsh: add interface information to guestinfo command qemu: refactor 'qemuAgentGetInterfaces' qemu: add guest interface information in 'qemuDomainGetGuestInfo' NEWS: add guest interface information in 'virDomainGetGuestInfo' NEWS.rst | 5 ++ docs/manpages/virsh.rst | 12 ++++- include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 12 +++++ src/qemu/qemu_agent.c | 9 ++-- src/qemu/qemu_agent.h | 3 +- src/qemu/qemu_driver.c | 90 +++++++++++++++++++++++++++++++- tests/qemuagenttest.c | 2 +- tools/virsh-domain.c | 6 +++ 9 files changed, 131 insertions(+), 9 deletions(-) -- 2.31.1

Signed-off-by: zhanglei <zhanglei@smartx.com> --- include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index eaafcc6b29..2f017c5b68 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5098,6 +5098,7 @@ typedef enum { VIR_DOMAIN_GUEST_INFO_HOSTNAME = (1 << 3), /* return hostname information */ VIR_DOMAIN_GUEST_INFO_FILESYSTEM = (1 << 4), /* return filesystem information */ VIR_DOMAIN_GUEST_INFO_DISKS = (1 << 5), /* return disks information */ + VIR_DOMAIN_GUEST_INFO_INTERFACES = (1 << 6), /* return interfaces information */ } virDomainGuestInfoTypes; int virDomainGetGuestInfo(virDomainPtr domain, diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 57baef6889..fdc0780ae0 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -12579,6 +12579,18 @@ virDomainSetVcpu(virDomainPtr domain, * * "hostname" - the hostname of the domain * + * VIR_DOMAIN_GUEST_INFO_INTERFACES: + * Returns information about the interfaces within the domain. the typed + * parameter keys are in this format: + * + * "if.count" - the number of interfaces defined on this domain + * "if.<num>.name" - name in the guest (e.g. ``eth0``) for interface <num> + * "if.<num>.hwaddr" - hardware address in the guest for interface <num> + * "if.<num>.addr.count - the number of IP addresses of interface <num> + * "if.<num>.addr.<num1>.type" - the IP address type of addr <num1> (e.g. ipv4) + * "if.<num>.addr.<num1>.addr" - the IP address of addr <num1> + * "if.<num>.addr.<num1>.prefix" - the prefix of IP address of addr <num1> + * * Using 0 for @types returns all information groups supported by the given * hypervisor. * -- 2.31.1

The new parameter group returns information about network interfaces Signed-off-by: zhanglei <zhanglei@smartx.com> --- docs/manpages/virsh.rst | 12 ++++++++++-- src/libvirt-domain.c | 2 +- tools/virsh-domain.c | 6 ++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 4c5341d00d..1c60eae607 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2700,7 +2700,7 @@ guestinfo :: guestinfo domain [--user] [--os] [--timezone] [--hostname] [--filesystem] - [--disk] + [--disk] [--interface] Print information about the guest from the point of view of the guest agent. Note that this command requires a guest agent to be configured and running in @@ -2711,7 +2711,7 @@ are supported by the guest agent. You can limit the types of information that are returned by specifying one or more flags. If a requested information type is not supported, the processes will provide an exit code of 1. Available information types flags are *--user*, *--os*, -*--timezone*, *--hostname*, *--filesystem* and *--disk*. +*--timezone*, *--hostname*, *--filesystem*, *--disk* and *--interface*. Note that depending on the hypervisor type and the version of the guest agent running within the domain, not all of the following information may be @@ -2779,6 +2779,14 @@ returned: * ``disk.<num>.alias`` - the device alias of the disk (e.g. sda) * ``disk.<num>.guest_alias`` - optional alias assigned to the disk +*--interface* returns: +* ``if.count`` - the number of interfaces defined on this domain +* ``if.<num>.name`` - name in the guest (e.g. ``eth0``) for interface <num> +* ``if.<num>.hwaddr`` - hardware address in the guest for interface <num> +* ``if.<num>.addr.count`` - the number of IP addresses of interface <num> +* ``if.<num>.addr.<num1>.type`` - the IP address type of addr <num1> (e.g. ipv4) +* ``if.<num>.addr.<num1>.addr`` - the IP address of addr <num1> +* ``if.<num>.addr.<num1>.prefix`` - the prefix of IP address of addr <num1> guestvcpus ---------- diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index fdc0780ae0..ce7cafde36 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -12580,7 +12580,7 @@ virDomainSetVcpu(virDomainPtr domain, * "hostname" - the hostname of the domain * * VIR_DOMAIN_GUEST_INFO_INTERFACES: - * Returns information about the interfaces within the domain. the typed + * Returns information about the interfaces within the domain. The typed * parameter keys are in this format: * * "if.count" - the number of interfaces defined on this domain diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index dbddefb4a5..bce03b3de5 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13999,6 +13999,10 @@ static const vshCmdOptDef opts_guestinfo[] = { .type = VSH_OT_BOOL, .help = N_("report disk information"), }, + {.name = "interface", + .type = VSH_OT_BOOL, + .help = N_("report interface information"), + }, {.name = NULL} }; @@ -14024,6 +14028,8 @@ cmdGuestInfo(vshControl *ctl, const vshCmd *cmd) types |= VIR_DOMAIN_GUEST_INFO_FILESYSTEM; if (vshCommandOptBool(cmd, "disk")) types |= VIR_DOMAIN_GUEST_INFO_DISKS; + if (vshCommandOptBool(cmd, "interface")) + types |= VIR_DOMAIN_GUEST_INFO_INTERFACES; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; -- 2.31.1

On a Friday in 2021, zhanglei wrote:
The new parameter group returns information about network interfaces
Signed-off-by: zhanglei <zhanglei@smartx.com> --- docs/manpages/virsh.rst | 12 ++++++++++-- src/libvirt-domain.c | 2 +- tools/virsh-domain.c | 6 ++++++ 3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index fdc0780ae0..ce7cafde36 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -12580,7 +12580,7 @@ virDomainSetVcpu(virDomainPtr domain, * "hostname" - the hostname of the domain * * VIR_DOMAIN_GUEST_INFO_INTERFACES: - * Returns information about the interfaces within the domain. the typed + * Returns information about the interfaces within the domain. The typed
This is fixing up the text added in patch 1/5. I have squashed the change there. Jano
* parameter keys are in this format: * * "if.count" - the number of interfaces defined on this domain

Add report_unsupported parameter to qemuAgentGetInterfaces Signed-off-by: zhanglei <zhanglei@smartx.com> --- src/qemu/qemu_agent.c | 9 ++++++--- src/qemu/qemu_agent.h | 3 ++- src/qemu/qemu_driver.c | 2 +- tests/qemuagenttest.c | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 5f421be6f6..a7f943e0dc 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -2245,17 +2245,20 @@ qemuAgentGetAllInterfaceAddresses(virDomainInterfacePtr **ifaces_ret, */ int qemuAgentGetInterfaces(qemuAgent *agent, - virDomainInterfacePtr **ifaces) + virDomainInterfacePtr **ifaces, + bool report_unsupported) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; virJSONValue *ret_array = NULL; + int rc; if (!(cmd = qemuAgentMakeCommand("guest-network-get-interfaces", NULL))) return -1; - if (qemuAgentCommand(agent, cmd, &reply, agent->timeout) < 0) - return -1; + if ((rc = qemuAgentCommandFull(agent, cmd, &reply, agent->timeout, + report_unsupported)) < 0) + return rc; if (!(ret_array = virJSONValueObjectGetArray(reply, "return"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 81b45b8e5d..94eab9de9f 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -151,7 +151,8 @@ int qemuAgentSetTime(qemuAgent *mon, bool sync); int qemuAgentGetInterfaces(qemuAgent *mon, - virDomainInterfacePtr **ifaces); + virDomainInterfacePtr **ifaces, + bool report_unsupported); int qemuAgentSetUserPassword(qemuAgent *mon, const char *user, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2b759f5719..7e058a9309 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19090,7 +19090,7 @@ qemuDomainInterfaceAddresses(virDomainPtr dom, goto endjob; agent = qemuDomainObjEnterAgent(vm); - ret = qemuAgentGetInterfaces(agent, ifaces); + ret = qemuAgentGetInterfaces(agent, ifaces, true); qemuDomainObjExitAgent(vm, agent); endjob: diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c index bef6dfd152..8fb3da7fef 100644 --- a/tests/qemuagenttest.c +++ b/tests/qemuagenttest.c @@ -907,7 +907,7 @@ testQemuAgentGetInterfaces(const void *data) goto cleanup; if ((ifaces_count = qemuAgentGetInterfaces(qemuMonitorTestGetAgent(test), - &ifaces)) < 0) + &ifaces, true)) < 0) goto cleanup; if (ifaces_count != 4) { -- 2.31.1

Support return guest interface information from guest agent Signed-off-by: zhanglei <zhanglei@smartx.com> --- src/qemu/qemu_driver.c | 88 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7e058a9309..0688964195 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20036,7 +20036,8 @@ static const unsigned int qemuDomainGetGuestInfoSupportedTypes = VIR_DOMAIN_GUEST_INFO_TIMEZONE | VIR_DOMAIN_GUEST_INFO_HOSTNAME | VIR_DOMAIN_GUEST_INFO_FILESYSTEM | - VIR_DOMAIN_GUEST_INFO_DISKS; + VIR_DOMAIN_GUEST_INFO_DISKS | + VIR_DOMAIN_GUEST_INFO_INTERFACES; static int qemuDomainGetGuestInfoCheckSupport(unsigned int types, @@ -20235,6 +20236,71 @@ qemuAgentFSInfoFormatParams(qemuAgentFSInfo **fsinfo, } } +static void +virDomainInterfaceFormatParams(virDomainInterfacePtr *ifaces, + int nifaces, + virTypedParameterPtr *params, + int *nparams, int * maxparams) +{ + size_t i; + size_t j; + const char *type = NULL; + + if (virTypedParamsAddUInt(params, nparams, maxparams, + "if.count", nifaces) < 0) + return; + + for (i = 0; i < nifaces; i++) { + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.name", i); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, ifaces[i]->name) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.hwaddr", i); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, ifaces[i]->hwaddr) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.addr.count", i); + if (virTypedParamsAddUInt(params, nparams, maxparams, + param_name, ifaces[i]->naddrs) < 0) + return; + + for (j = 0; j < ifaces[i]->naddrs; j++) { + switch (ifaces[i]->addrs[j].type) { + case VIR_IP_ADDR_TYPE_IPV4: + type = "ipv4"; + break; + case VIR_IP_ADDR_TYPE_IPV6: + type = "ipv6"; + break; + } + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.addr.%zu.type", i, j); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, type) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.addr.%zu.addr", i, j); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, ifaces[i]->addrs[j].addr) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.addr.%zu.prefix", i, j); + if (virTypedParamsAddUInt(params, nparams, maxparams, + param_name, ifaces[i]->addrs[j].prefix) < 0) + return; + } + } +} static int qemuDomainGetGuestInfo(virDomainPtr dom, @@ -20256,6 +20322,8 @@ qemuDomainGetGuestInfo(virDomainPtr dom, qemuAgentFSInfo **agentfsinfo = NULL; size_t ndisks = 0; qemuAgentDiskInfo **agentdiskinfo = NULL; + virDomainInterfacePtr *ifaces = NULL; + size_t nifaces = 0; size_t i; virCheckFlags(0, -1); @@ -20321,6 +20389,15 @@ qemuDomainGetGuestInfo(virDomainPtr dom, } } + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_INTERFACES) { + rc = qemuAgentGetInterfaces(agent, &ifaces, report_unsupported); + if (rc == -1) { + goto exitagent; + } else if (rc >= 0) { + nifaces = rc; + } + } + qemuDomainObjExitAgent(vm, agent); qemuDomainObjEndAgentJob(vm); @@ -20343,6 +20420,10 @@ qemuDomainGetGuestInfo(virDomainPtr dom, qemuDomainObjEndJob(driver, vm); } + if (nifaces > 0) { + virDomainInterfaceFormatParams(ifaces, nifaces, params, nparams, &maxparams); + } + ret = 0; cleanup: @@ -20352,6 +20433,11 @@ qemuDomainGetGuestInfo(virDomainPtr dom, 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; -- 2.31.1

On a Friday in 2021, zhanglei wrote:
Support return guest interface information from guest agent
Signed-off-by: zhanglei <zhanglei@smartx.com> --- src/qemu/qemu_driver.c | 88 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7e058a9309..0688964195 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20036,7 +20036,8 @@ static const unsigned int qemuDomainGetGuestInfoSupportedTypes = VIR_DOMAIN_GUEST_INFO_TIMEZONE | VIR_DOMAIN_GUEST_INFO_HOSTNAME | VIR_DOMAIN_GUEST_INFO_FILESYSTEM | - VIR_DOMAIN_GUEST_INFO_DISKS; + VIR_DOMAIN_GUEST_INFO_DISKS | + VIR_DOMAIN_GUEST_INFO_INTERFACES;
static int qemuDomainGetGuestInfoCheckSupport(unsigned int types, @@ -20235,6 +20236,71 @@ qemuAgentFSInfoFormatParams(qemuAgentFSInfo **fsinfo, } }
+static void +virDomainInterfaceFormatParams(virDomainInterfacePtr *ifaces, + int nifaces, + virTypedParameterPtr *params, + int *nparams, int * maxparams)
No space after the '*' is the prevailing libvirt style.
+{ + size_t i; + size_t j; + const char *type = NULL; + + if (virTypedParamsAddUInt(params, nparams, maxparams, + "if.count", nifaces) < 0) + return; + + for (i = 0; i < nifaces; i++) { + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.name", i); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, ifaces[i]->name) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.hwaddr", i); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, ifaces[i]->hwaddr) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "if.%zu.addr.count", i); + if (virTypedParamsAddUInt(params, nparams, maxparams, + param_name, ifaces[i]->naddrs) < 0) + return; + + for (j = 0; j < ifaces[i]->naddrs; j++) {
'type' is only used within this block so its scope can be reduced.
+ switch (ifaces[i]->addrs[j].type) { + case VIR_IP_ADDR_TYPE_IPV4: + type = "ipv4"; + break; + case VIR_IP_ADDR_TYPE_IPV6: + type = "ipv6"; + break; + }
Jano

Signed-off-by: zhanglei <zhanglei@smartx.com> --- NEWS.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index ae678bffc4..0d343bf33c 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -42,6 +42,11 @@ v7.9.0 (unreleased) * **Improvements** + * qemu: Report guest interface information in ``virDomainGetGuestInfo`` + + Libvirt is now able to report interface information from the guest's + perspective (using guest agent). + * **Bug fixes** -- 2.31.1

On a Friday in 2021, zhanglei wrote:
zhanglei (5): domain: add interface information to 'virDomainGetGuestInfo' virsh: add interface information to guestinfo command qemu: refactor 'qemuAgentGetInterfaces' qemu: add guest interface information in 'qemuDomainGetGuestInfo' NEWS: add guest interface information in 'virDomainGetGuestInfo'
NEWS.rst | 5 ++ docs/manpages/virsh.rst | 12 ++++- include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 12 +++++ src/qemu/qemu_agent.c | 9 ++-- src/qemu/qemu_agent.h | 3 +- src/qemu/qemu_driver.c | 90 +++++++++++++++++++++++++++++++- tests/qemuagenttest.c | 2 +- tools/virsh-domain.c | 6 +++ 9 files changed, 131 insertions(+), 9 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> and pushed (with the changes I pointed out) Jano
participants (2)
-
Ján Tomko
-
zhanglei