[libvirt PATCH v2 3/4] qemu: report guest interface information in 'qemuDomainGetGuestInfo'

zhanglei posted 4 patches 4 years, 4 months ago
[libvirt PATCH v2 3/4] qemu: report guest interface information in 'qemuDomainGetGuestInfo'
Posted by zhanglei 4 years, 4 months ago
Signed-off-by: zhanglei <zhanglei@smartx.com>
---
 src/qemu/qemu_agent.c  |  9 +++--
 src/qemu/qemu_agent.h  |  3 +-
 src/qemu/qemu_driver.c | 89 +++++++++++++++++++++++++++++++++++++++++-
 tests/qemuagenttest.c  |  2 +-
 4 files changed, 96 insertions(+), 7 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 dfc27572c4..ec5bf0a451 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18950,7 +18950,7 @@ qemuDomainInterfaceAddresses(virDomainPtr dom,
             goto endjob;
 
         agent = qemuDomainObjEnterAgent(vm);
-        ret = qemuAgentGetInterfaces(agent, ifaces);
+        ret = qemuAgentGetInterfaces(agent, ifaces, true);
         qemuDomainObjExitAgent(vm, agent);
 
     endjob:
@@ -19896,7 +19896,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,
@@ -20095,6 +20096,70 @@ qemuAgentFSInfoFormatParams(qemuAgentFSInfo **fsinfo,
     }
 }
 
+static void
+virDomainInterfaceFormatParams(virDomainInterfacePtr *ifaces,
+int nifaces,
+virTypedParameterPtr *params,
+int *nparams, int * maxparams)
+{
+    size_t i, 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,
@@ -20116,6 +20181,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);
@@ -20181,6 +20248,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);
 
@@ -20203,6 +20279,10 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
         qemuDomainObjEndJob(driver, vm);
     }
 
+    if (nifaces > 0) {
+        virDomainInterfaceFormatParams(ifaces, nifaces, params, nparams, &maxparams);
+    }
+
     ret = 0;
 
  cleanup:
@@ -20212,6 +20292,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;
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

Re: [libvirt PATCH v2 3/4] qemu: report guest interface information in 'qemuDomainGetGuestInfo'
Posted by Peter Krempa 4 years, 4 months ago
On Tue, Sep 14, 2021 at 15:56:44 +0800, zhanglei wrote:

Please describe your changes in more detail.

> Signed-off-by: zhanglei <zhanglei@smartx.com>
> ---
>  src/qemu/qemu_agent.c  |  9 +++--
>  src/qemu/qemu_agent.h  |  3 +-
>  src/qemu/qemu_driver.c | 89 +++++++++++++++++++++++++++++++++++++++++-
>  tests/qemuagenttest.c  |  2 +-
>  4 files changed, 96 insertions(+), 7 deletions(-)

[...]

> 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);

The addition of 'report_unsupported' and the refactor to existing code
to pass it can be split into a separate commit to reduce noise.

> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index dfc27572c4..ec5bf0a451 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c

[...]

> +static void
> +virDomainInterfaceFormatParams(virDomainInterfacePtr *ifaces,
> +int nifaces,
> +virTypedParameterPtr *params,
> +int *nparams, int * maxparams)

The function header is totally malformated. There are also multiple
other instances of broken alignment below. I'll mark them with '***'

> +{
> +    size_t i, j;

One variable declaration per line please;

> +    const char *type = NULL;
> +
> +    if (virTypedParamsAddUInt(params, nparams, maxparams,
> +                             "if.count", nifaces) < 0)
> +      return;

Checking the return code and not reporting error feels a bit weird, but
I guess you've got the inspiration from the existing code which does the
same, so it's okay for now.

> +
> +    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;

***

And many more below. I give up, this function has totally broken
formatting.

> +
> +           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;
> +        }
> +    }
> +}