diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 11ffd07a187efb014b5b173efdbfd49952e24ec1..a026b9aa6c1dadf86e829abceda09b9d0bde978f 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3739,5 +3739,37 @@ typedef struct _virTypedParameter virMemoryParameter; */ typedef virMemoryParameter *virMemoryParameterPtr; +typedef enum { + VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0, /* Parse DHCP lease file */ + VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT = 1, /* Query qemu guest agent */ + +# ifdef VIR_ENUM_SENTINELS + VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST +# endif +} virDomainInterfaceAddressesSource; + +typedef struct _virDomainInterfaceIPAddress virDomainIPAddress; +typedef virDomainIPAddress *virDomainIPAddressPtr; +struct _virDomainInterfaceIPAddress { + int type; /* virIPAddrType */ + char *addr; /* IP address */ + unsigned int prefix; /* IP address prefix */ +}; + +typedef struct _virDomainInterface virDomainInterface; +typedef virDomainInterface *virDomainInterfacePtr; +struct _virDomainInterface { + char *name; /* interface name */ + char *hwaddr; /* hardware address */ + unsigned int naddrs; /* number of items in @addrs */ + virDomainIPAddressPtr addrs; /* array of IP addresses */ +}; + +int virDomainInterfaceAddresses(virDomainPtr dom, + virDomainInterfacePtr **ifaces, + unsigned int source, + unsigned int flags); + +void virDomainInterfaceFree(virDomainInterfacePtr iface); #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 1617d0a1979a489670595187613a19897e61fda9..3f9bf02ac084e15f92c2c024179837ae381d1243 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1185,6 +1185,11 @@ typedef int unsigned int cellCount, unsigned int flags); +typedef int +(*virDrvDomainInterfaceAddresses)(virDomainPtr dom, + virDomainInterfacePtr **ifaces, + unsigned int source, + unsigned int flags); typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1412,6 +1417,7 @@ struct _virHypervisorDriver { virDrvConnectGetAllDomainStats connectGetAllDomainStats; virDrvNodeAllocPages nodeAllocPages; virDrvDomainGetFSInfo domainGetFSInfo; + virDrvDomainInterfaceAddresses domainInterfaceAddresses; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index bc13165ada38c420f53a33a6cf81dc9059c01f16..a3f179d9d4bae979d29fc75d1bcefdb34225a43e 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11416,3 +11416,122 @@ virDomainFSInfoFree(virDomainFSInfoPtr info) VIR_FREE(info); } + +/** + * virDomainInterfaceAddresses: + * @dom: domain object + * @ifaces: pointer to an array of pointers pointing to interface objects + * @source: one of the virDomainInterfaceAddressesSource constants + * @flags: currently unused, pass zero + * + * Return a pointer to the allocated array of pointers to interfaces + * present in given domain along with their IP and MAC addresses. Note that + * single interface can have multiple or even 0 IP addresses. + * + * This API dynamically allocates the virDomainInterfacePtr struct based on + * how many interfaces domain @dom has, usually there's 1:1 correlation. The + * count of the interfaces is returned as the return value. + * + * If @source is VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE, the DHCP lease + * file associated with any virtual networks will be examined to obtain + * the interface addresses. This only returns data for interfaces which + * are connected to virtual networks managed by libvirt. + * + * If @source is VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT, a configured + * guest agent is needed for successful return from this API. Moreover, if + * guest agent is used then the interface name is the one seen by guest OS. + * To match such interface with the one from @dom XML use MAC address or IP + * range. + * + * @ifaces->name and @ifaces->hwaddr are never NULL. + * + * The caller *must* free @ifaces when no longer needed. Usual use case + * looks like this: + * + * virDomainInterfacePtr *ifaces = NULL; + * int ifaces_count = 0; + * size_t i, j; + * virDomainPtr dom = ... obtain a domain here ...; + * + * if ((ifaces_count = virDomainInterfaceAddresses(dom, &ifaces, + * VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)) < 0) + * goto cleanup; + * + * ... do something with returned values, for example: + * for (i = 0; i < ifaces_count; i++) { + * printf("name: %s", ifaces[i]->name); + * printf(" hwaddr: %s", ifaces[i]->hwaddr); + * + * for (j = 0; j < ifaces[i]->naddrs; j++) { + * virDomainIPAddressPtr ip_addr = ifaces[i]->addrs + j; + * printf("[addr: %s prefix: %d type: %d]", + * ip_addr->addr, ip_addr->prefix, ip_addr->type); + * } + * printf("\n"); + * } + * + * cleanup: + * if (ifaces && ifaces_count > 0) + * for (i = 0; i < ifaces_count; i++) + * virDomainInterfaceFree(ifaces[i]); + * free(ifaces); + * + * Returns the number of interfaces on success, -1 in case of error. + */ +int +virDomainInterfaceAddresses(virDomainPtr dom, + virDomainInterfacePtr **ifaces, + unsigned int source, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(dom, "ifaces=%p, source=%d, flags=%x", ifaces, source, flags); + + virResetLastError(); + + if (ifaces) + *ifaces = NULL; + virCheckDomainReturn(dom, -1); + virCheckNonNullArgGoto(ifaces, error); + virCheckReadOnlyGoto(dom->conn->flags, error); + + if (dom->conn->driver->domainInterfaceAddresses) { + int ret; + ret = dom->conn->driver->domainInterfaceAddresses(dom, ifaces, source, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + + error: + virDispatchError(dom->conn); + return -1; +} + + +/** + * virDomainInterfaceFree: + * @iface: an interface object + * + * Free the interface object. The data structure is + * freed and should not be used thereafter. If @iface + * is NULL, then this method has no effect. + */ +void +virDomainInterfaceFree(virDomainInterfacePtr iface) +{ + size_t i; + + if (!iface) + return; + + VIR_FREE(iface->name); + VIR_FREE(iface->hwaddr); + + for (i = 0; i < iface->naddrs; i++) + VIR_FREE(iface->addrs[i].addr); + VIR_FREE(iface->addrs); + + VIR_FREE(iface); +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 803d5a1f971f8b0674b830644acdb2186e94f6d4..e4cf7ed24dc22b00aae6cbe244ae4f27eaa21f0c 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -700,6 +700,8 @@ LIBVIRT_1.2.14 { virDomainIOThreadsInfoFree; virDomainGetIOThreadsInfo; virDomainPinIOThread; + virDomainInterfaceAddresses; + virDomainInterfaceFree; } LIBVIRT_1.2.12; # .... define new API here using predicted next version number ....