On 15/08/13 04:54, nehaljwani wrote:
Define a new API virDomainInterfacesAddresses, which returns
the address information of a running domain's interfaces(s).
If no interface name is specified, it returns the information
of all interfaces, otherwise it only returns the information
of the specificed interface. The address information includes
the MAC and IP addresses.
The API is going to provide multiple methods by flags, e.g.
* Query guest agent
* Parse lease file of dnsmasq
* DHCP snooping
But at this stage, it will only work with guest agent, and flags
won't be supported.
include/libvirt/libvirt.h.in:
* Define virDomainInterfacesAddresses
* Define structs virDomainInterface, virDomainIPAddress
python/generator.py:
* Skip the auto-generation for virDomainInterfacesAddresses
src/driver.h:
* Define domainInterfacesAddresses
src/libvirt.c:
* Implement virDomainInterfacesAddresses
src/libvirt_public.syms:
* Export the new symbol
---
include/libvirt/libvirt.h.in | 32 ++++++++++++++
python/generator.py | 1 +
src/driver.h | 7 ++++
src/libvirt.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++
5 files changed, 144 insertions(+)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 52ac95d..fa49e70 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2044,6 +2044,38 @@ int virDomainGetInterfaceParameters
(virDomainPtr dom,
virTypedParameterPtr params,
int *nparams, unsigned int
flags);
+typedef enum {
+ VIR_IP_ADDR_TYPE_IPV4,
+ VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+ VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+
+typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;
+typedef virDomainIPAddress *virDomainIPAddressPtr;
+struct _virDomainInterfaceIPAddress {
+ int type; /* virIPAddrType */
+ char *addr; /* IP address */
+ int prefix; /* IP address prefix */
+};
+
+typedef struct _virDomainInterface virDomainInterface;
+typedef virDomainInterface *virDomainInterfacePtr;
+struct _virDomainInterface {
+ char *name; /* interface name */
+ char *hwaddr; /* hardware address */
+ unsigned int ip_addrs_count; /* number of items in @ip_addr */
+ virDomainIPAddressPtr ip_addrs; /* array of IP addresses */
+};
+
+int virDomainInterfacesAddresses (virDomainPtr dom,
+ virDomainInterfacePtr *ifaces,
+ unsigned int *ifaces_count,
+ unsigned int flags);
+
/* Management of domain block devices */
int virDomainBlockPeek (virDomainPtr dom,
diff --git a/python/generator.py b/python/generator.py
index 427cebc..ceef9a7 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -458,6 +458,7 @@ skip_impl = (
'virNodeGetMemoryParameters',
'virNodeSetMemoryParameters',
'virNodeGetCPUMap',
+ 'virDomainInterfacesAddresses',
'virDomainMigrate3',
'virDomainMigrateToURI3',
)
diff --git a/src/driver.h b/src/driver.h
index be64333..dfb75b1 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -518,6 +518,12 @@ typedef int
unsigned int flags);
typedef int
+(*virDrvDomainInterfacesAddresses)(virDomainPtr dom,
+ virDomainInterfacePtr *ifaces,
+ unsigned int *ifaces_count,
+ unsigned int flags);
+
+typedef int
(*virDrvDomainMemoryStats)(virDomainPtr domain,
struct _virDomainMemoryStat *stats,
unsigned int nr_stats,
@@ -1238,6 +1244,7 @@ struct _virDriver {
virDrvDomainInterfaceStats domainInterfaceStats;
virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
+ virDrvDomainInterfacesAddresses domainInterfacesAddresses;
virDrvDomainMemoryStats domainMemoryStats;
virDrvDomainBlockPeek domainBlockPeek;
virDrvDomainMemoryPeek domainMemoryPeek;
diff --git a/src/libvirt.c b/src/libvirt.c
index 66e8248..d816304 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8643,6 +8643,105 @@ error:
return -1;
}
+ /**
+ * virDomainInterfacesAddresses:
+ * @dom: domain object
+ * @ifaces: array of @dom interfaces
+ * @ifaces_count: number of items in @ifaces
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Return an array of interfaces present in given domain along with
+ * their IP and MAC addresses. Note that single interface can have
+ * multiple or even 0 IP address.
+ *
+ * This API dynamically allocates the virDomainInterfacePtr struct
+ * based on how many interfaces domain @dom has, usually there's
+ * 1:1 correlation. The count of elements allocated is stored in
+ * @ifaces_count.
+ *
+ * Note that for some hypervisors, 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 is never NULL, @ifaces->hwaddr might be NULL.
+ *
+ * The caller *must* free @ifaces when no longer needed. Usual use
+ * case looks like this:
+ *
+ * virDomainInterfacePtr ifaces = NULL;
+ * unsigned int ifaces_count = 0;
+ * size_t i, j;
+ * virDomainPtr dom = ... obtain a domain here ...;
+ *
+ * if (virDomainInterfacesAddresses(dom, &ifaces, &ifaces_count, 0) < 0)
+ * goto cleanup;
+ *
+ * ... do something with returned values, for example:
+ * for (i = 0; i < ifaces_count; i++) {
+ * printf("name: %s", ifaces[i].name);
+ * if (ifaces[i].hwaddr)
+ * printf(" hwaddr: %s", ifaces[i].hwaddr);
+ *
+ * for (j = 0; j < ifaces[i].ip_addrs_count; j++) {
+ * virDomainIPAddressPtr ip_addr = ifaces[i].ip_addrs + j;
+ * printf("[addr: %s prefix: %d type: %d]",
+ * ip_addr->addr, ip_addr->prefix, ip_addr->type);
+ * }
+ * printf("\n");
+ * }
+ *
+ * cleanup:
+ * for (i = 0; i < ifaces_count; i++) {
+ * free(ifaces[i].name);
+ * free(ifaces[i].hwaddr);
+ * for (j = 0; j < ifaces[i].ip_addrs_count; j++)
+ * free(ifaces[i].ip_addrs[j].addr);
+ * free(ifaces[i].ip_addrs);
+ * }
+ * free(ifaces);
+ *
+ * Returns 0 on success, -1 in case of error.
+ */
+int
+virDomainInterfacesAddresses(virDomainPtr dom,
+ virDomainInterfacePtr *ifaces,
+ unsigned int *ifaces_count,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(dom, "ifaces=%p, ifaces_count=%p, flags=%x",
+ ifaces, ifaces_count, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(dom)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ goto error;
+ }
+
+ conn = dom->conn;
+
+ virCheckNonNullArgGoto(ifaces, error);
+ virCheckNonNullArgGoto(ifaces_count, error);
+
+ if (conn->driver->domainInterfacesAddresses) {
+ int ret;
+ ret = conn->driver->domainInterfacesAddresses(dom, ifaces,
+ ifaces_count, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(dom ? dom->conn : NULL);
+ return -1;
+}
+
/**
* virDomainMemoryStats:
* @dom: pointer to the domain object
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index bbdf78a..6cbcfb4 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -634,4 +634,9 @@ LIBVIRT_1.1.1 {
virDomainSetMemoryStatsPeriod;
} LIBVIRT_1.1.0;
+LIBVIRT_1.1.2 {
+ global:
+ virDomainInterfacesAddresses;
+} LIBVIRT_1.1.1;
+
# .... define new API here using predicted next version number ....
Previous ACK stands.