Signed-off-by: scuzhanglei <greatzhanglei(a)gmail.com>
---
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 | 88 +++++++++++++++++++++++++++++++-
tests/qemuagenttest.c | 2 +-
tools/virsh-domain.c | 6 +++
9 files changed, 129 insertions(+), 9 deletions(-)
diff --git a/NEWS.rst b/NEWS.rst
index 1af934e068..8666b318d8 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -45,6 +45,11 @@ v7.7.0 (unreleased)
The genid attribute is now reported for VMX guests. Libvirt can now
properly process super wide SCSI bus (64 units).
+ * qemu: Report guest interfaces information in ``virDomainGetGuestInfo``
+
+ Libvirt is now able to report interfaces from the guest's
+ perspective (using guest agent).
+
* **Bug fixes**
* qemu: Open chardev logfile on behalf of QEMU
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 2204bed3bb..9f878d400c 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.<num>.type`` - the type of IP address <num> (e.g.
ipv4)
+* ``if.<num>.addr.<num>.addr`` - the address of IP address <num>
+* ``if.<num>.addr.<num>.prefix`` - the prefix of IP address <num>
guestvcpus
----------
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 7ef8ac51e5..b088847725 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -5074,6 +5074,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 a8a386e839..dfd84b4744 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12586,6 +12586,18 @@ virDomainSetVcpu(virDomainPtr domain,
* virTypedParamsFree to free memory returned in @params.
*
* Returns 0 on success, -1 on error.
+ * 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
+ * as an unsigned int
+ * "if.<num>.name" - interface name in the guest
+ * "if.<num>.hwaddr" - hardware address of interface
+ * "if.<num>.addr.count - the number of ip addresses of interface
+ * "if.<num>.addr.<num>.type" - the type of ip address(e.g.
ipv4)
+ * "if.<num>.addr.<num>.addr" - the ip address
+ * "if.<num>.addr.<num>.prefix" - the number of bits of ip
address prefix
*/
int virDomainGetGuestInfo(virDomainPtr domain,
unsigned int types,
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 f1f961c51c..0b803c392b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18957,7 +18957,7 @@ qemuDomainInterfaceAddresses(virDomainPtr dom,
goto endjob;
agent = qemuDomainObjEnterAgent(vm);
- ret = qemuAgentGetInterfaces(agent, ifaces);
+ ret = qemuAgentGetInterfaces(agent, ifaces, true);
qemuDomainObjExitAgent(vm, agent);
endjob:
@@ -19903,7 +19903,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,
@@ -20102,6 +20103,69 @@ 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,
@@ -20123,6 +20187,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);
@@ -20188,6 +20254,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);
@@ -20210,6 +20285,10 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
qemuDomainObjEndJob(driver, vm);
}
+ if (nifaces > 0) {
+ virDomainInterfaceFormatParams(ifaces, nifaces, params, nparams,
&maxparams);
+ }
+
ret = 0;
cleanup:
@@ -20219,6 +20298,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 a447c93494..e0b22c042a 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -920,7 +920,7 @@ testQemuAgentGetInterfaces(const void *data)
goto cleanup;
if ((ifaces_count = qemuAgentGetInterfaces(qemuMonitorTestGetAgent(test),
- &ifaces)) < 0)
+ &ifaces, true)) < 0)
goto cleanup;
if (ifaces_count != 4) {
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index e5bd1fdd75..5ba5bd6b8c 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13829,6 +13829,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}
};
@@ -13854,6 +13858,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