--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list