[libvirt] [PATCHv5 1/5] domifaddr: Implement the public APIs
Nehal J Wani
nehaljw.kkd1 at gmail.com
Mon Sep 2 09:41:14 UTC 2013
On Sun, Sep 1, 2013 at 7:13 PM, Nehal J Wani <nehaljw.kkd1 at gmail.com> wrote:
> Define a new API virDomainInterfaceAddresses, 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.
>
> Define helper function virDomainInterfaceFree, which allows
> the upper layer application to free the domain interface object
> conveniently.
>
> 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 virDomainInterfaceAddresses, virDomainInterfaceFree
> * Define structs virDomainInterface, virDomainIPAddress
>
> python/generator.py:
> * Skip the auto-generation for virDomainInterfaceAddresses
> and virDomainInterfaceFree
>
> src/driver.h:
> * Define domainInterfaceAddresses
>
> src/libvirt.c:
> * Implement virDomainInterfaceAddresses
> * Implement virDomainInterfaceFree
>
> src/libvirt_public.syms:
> * Export the new symbols
>
> ---
> include/libvirt/libvirt.h.in | 32 ++++++++++++
> python/generator.py | 3 ++
> src/driver.h | 6 +++
> src/libvirt.c | 115 +++++++++++++++++++++++++++++++++++++++++++
> src/libvirt_public.syms | 6 +++
> 5 files changed, 162 insertions(+)
>
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index a47e33c..1a34d02 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 */
> + 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 flags);
> +
> +void virDomainInterfaceFree(virDomainInterfacePtr iface);
> +
> /* Management of domain block devices */
>
> int virDomainBlockPeek (virDomainPtr dom,
> diff --git a/python/generator.py b/python/generator.py
> index fb321c6..50f779b 100755
> --- a/python/generator.py
> +++ b/python/generator.py
> @@ -458,6 +458,7 @@ skip_impl = (
> 'virNodeGetMemoryParameters',
> 'virNodeSetMemoryParameters',
> 'virNodeGetCPUMap',
> + 'virDomainInterfaceAddresses',
> 'virDomainMigrate3',
> 'virDomainMigrateToURI3',
> )
> @@ -560,6 +561,8 @@ skip_function = (
> "virTypedParamsGetString",
> "virTypedParamsGetUInt",
> "virTypedParamsGetULLong",
> +
> + "virDomainInterfaceFree", # Only useful in C
> )
>
> lxc_skip_function = (
> diff --git a/src/driver.h b/src/driver.h
> index be64333..eb4927b 100644
> --- a/src/driver.h
> +++ b/src/driver.h
> @@ -518,6 +518,11 @@ typedef int
> unsigned int flags);
>
> typedef int
> +(*virDrvDomainInterfaceAddresses)(virDomainPtr dom,
> + virDomainInterfacePtr **ifaces,
> + unsigned int flags);
> +
> +typedef int
> (*virDrvDomainMemoryStats)(virDomainPtr domain,
> struct _virDomainMemoryStat *stats,
> unsigned int nr_stats,
> @@ -1238,6 +1243,7 @@ struct _virDriver {
> virDrvDomainInterfaceStats domainInterfaceStats;
> virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
> virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
> + virDrvDomainInterfaceAddresses domainInterfaceAddresses;
> virDrvDomainMemoryStats domainMemoryStats;
> virDrvDomainBlockPeek domainBlockPeek;
> virDrvDomainMemoryPeek domainMemoryPeek;
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 07a3fd5..82c117f 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -8643,6 +8643,96 @@ error:
> return -1;
> }
>
> + /**
> + * virDomainInterfaceAddresses:
> + * @dom: domain object
> + * @ifaces: pointer to an array of pointers pointing to interface objects
> + * @flags: extra flags; not used yet, so callers should always pass 0
> + *
> + * Return a pointer to the allocated array of pointers pointing to 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 the interfaces is returned as the return value.
> + *
> + * 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;
> + * int ifaces_count = 0;
> + * size_t i, j;
> + * virDomainPtr dom = ... obtain a domain here ...;
> + *
> + * if ((ifaces_count = virDomainInterfaceAddresses(dom, &ifaces, 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]->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)
> + * for (i = 0; i < ifaces_count; i++)
> + * virDomainInterfaceFree(ifaces[i]);
> + * VIR_FREE(ifaces);
> + *
> + * Returns the number of interfaces on success, -1 in case of error.
> + */
> +int
> +virDomainInterfaceAddresses(virDomainPtr dom,
> + virDomainInterfacePtr **ifaces,
> + unsigned int flags)
> +{
> + virConnectPtr conn;
> +
> + VIR_DOMAIN_DEBUG(dom, "ifaces=%p, flags=%x", ifaces, flags);
> +
> + virResetLastError();
> +
> + if (!VIR_IS_CONNECTED_DOMAIN(dom)) {
> + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + conn = dom->conn;
> +
> + virCheckNonNullArgGoto(ifaces, error);
> +
> + if (conn->driver->domainInterfaceAddresses) {
> + int ret;
> + ret = conn->driver->domainInterfaceAddresses(dom, ifaces, flags);
> + if (ret < 0)
> + goto error;
> + return ret;
> + }
> +
> + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
> +
> +error:
> + virDispatchError(dom->conn);
> + return -1;
> +}
> +
> /**
> * virDomainMemoryStats:
> * @dom: pointer to the domain object
> @@ -21961,3 +22051,28 @@ 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.
> + */
> +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 bbdf78a..35f3a3e 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -634,4 +634,10 @@ LIBVIRT_1.1.1 {
> virDomainSetMemoryStatsPeriod;
> } LIBVIRT_1.1.0;
>
> +LIBVIRT_1.1.3 {
> + global:
> + virDomainInterfaceAddresses;
> + virDomainInterfaceFree;
> +} LIBVIRT_1.1.1;
> +
> # .... define new API here using predicted next version number ....
> --
> 1.7.11.7
>
In agreement with Guido's suggestion on 5/5 of the previous version
(https://www.redhat.com/archives/libvir-list/2013-August/msg01271.html),
the enums are also to exposed to python bindings, for which,
/include/libvirt/libvirt.h.in will have to be modified a bit. Diff has
been attached.
--
Nehal J Wani
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 1.diff
Type: application/octet-stream
Size: 640 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20130902/87fde700/attachment-0001.obj>
More information about the libvir-list
mailing list