---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_driver.c | 76 ++++++++++++++++++++++++++++++++++++++++++
tools/virsh-domain-monitor.c | 19 ++++++++++
tools/virsh.pod | 19 +++++-----
4 files changed, 106 insertions(+), 9 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index d5d131a..7f25a0a 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1742,6 +1742,7 @@ struct _virDomainInterface {
typedef enum {
VIR_DOMAIN_INTERFACE_ADDRS_DEFAULT = 0, /* hypervisor choice */
+ VIR_DOMAIN_INTERFACE_ADDRS_GUEST_AGENT = (1 << 0), /* use guest agent */
} virDomainInterfacesAddressesFlags;
int virDomainInterfacesAddresses (virDomainPtr dom,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 270e4dd..f90ab41 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13173,6 +13173,81 @@ qemuListAllDomains(virConnectPtr conn,
return ret;
}
+static int
+qemuDomainInterfacesAddresses(virDomainPtr dom,
+ virDomainInterfacePtr *ifaces,
+ unsigned int flags)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ qemuDomainObjPrivatePtr priv = NULL;
+ virDomainObjPtr vm = NULL;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_INTERFACE_ADDRS_DEFAULT |
+ VIR_DOMAIN_INTERFACE_ADDRS_GUEST_AGENT, -1);
+
+ if (!ifaces) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("ifaces cannot be NULL"));
+ return -1;
+ }
+
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"),
uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ if (priv->agentError) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("QEMU guest agent is not "
+ "available due to an error"));
+ goto cleanup;
+ }
+
+ if (!priv->agent) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("QEMU guest agent is not configured"));
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto endjob;
+ }
+
+ qemuDomainObjEnterAgent(driver, vm);
+ ret = qemuAgentGetInterfaces(priv->agent, ifaces);
+ qemuDomainObjExitAgent(driver, vm);
+
+endjob:
+ if (qemuDomainObjEndJob(driver, vm) == 0)
+ vm = NULL;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
static virDriver qemuDriver = {
.no = VIR_DRV_QEMU,
.name = QEMU_DRIVER_NAME,
@@ -13338,6 +13413,7 @@ static virDriver qemuDriver = {
.domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
.domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
.domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
+ .domainInterfacesAddresses = qemuDomainInterfacesAddresses, /* 0.10.0 */
};
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index fb6fe23..b4a5088 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1694,6 +1694,7 @@ static const vshCmdInfo info_domifaddr[] = {
static const vshCmdOptDef opts_domifaddr[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or
uuid")},
{"interface", VSH_OT_DATA, VSH_OFLAG_NONE, N_("network interface
name")},
+ {"mode", VSH_OT_STRING, VSH_OFLAG_NONE, N_("querying mode:
default|agent")},
{NULL, 0, 0, NULL}
};
@@ -1703,6 +1704,7 @@ cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
virDomainPtr dom = NULL;
const char *device = NULL;
virDomainInterfacePtr ifaces = NULL;
+ const char *mode = NULL;
int i, j, ifaces_count = 0;
unsigned int flags = 0;
bool ret = false;
@@ -1717,6 +1719,23 @@ cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
}
+ if (vshCommandOptString(cmd, "mode", &mode) < 0) {
+ vshError(ctl, "%s", _("Invalid type"));
+ return false;
+ }
+
+ if (mode) {
+ if (STREQ(mode, "default")) {
+ flags |= VIR_DOMAIN_INTERFACE_ADDRS_DEFAULT;
+ } else if (STREQ(mode, "agent")) {
+ flags |= VIR_DOMAIN_INTERFACE_ADDRS_GUEST_AGENT;
+ } else {
+ vshError(ctl, _("Unknown mode %s value, "
+ "expecting 'default' or 'agent'"),
mode);
+ return false;
+ }
+ }
+
ifaces_count = virDomainInterfacesAddresses(dom, &ifaces, flags);
if (ifaces_count < 0) {
vshError(ctl, _("Failed to query for interfaces addresses"));
diff --git a/tools/virsh.pod b/tools/virsh.pod
index daf5889..f4f7a33 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -605,15 +605,16 @@ B<Explanation of fields> (fields appear in the folowing
order):
flush_total_times - total time flush operations took (ns)
<-- other fields provided by hypervisor -->
-=item B<domifaddr> I<domain> [I<interface-device>]
-
-Get a list of interfaces of domain among with their IP and hardware
-addresses, or if I<interface-device> is specified limit output just
-for that one interface. Note, that interface name can be driver
-dependent meaning it can be name within guest OS or the name you would
-see in domain XML. Moreover, the whole command may require a guest
-agent to be configured for the queried domain under some drivers,
-notably qemu.
+=item B<domifaddr> [I<--mode default,agent>] I<domain>
[I<interface-device>]
+
+Get a list of interfaces of domain among with their IP and hardware addresses,
+or if I<interface-device> is specified limit output just for that one
+interface. Note, that interface name can be driver dependent meaning it can be
+name within guest OS or the name you would see in domain XML. Moreover, upon
+I<--mode> choice command may require a guest agent to be configured for the
+queried domain under some drivers, notably qemu. Accepted values for I<--mode>
+are 'default' (meaning hypervisor will choose the most suitable method) and
+'agent' (guest agent is used).
=item B<domifstat> I<domain> I<interface-device>
--
1.7.8.6