[libvirt] [PATCHv5 5/5] domifaddr: Expose python binding

Nehal J Wani nehaljw.kkd1 at gmail.com
Mon Sep 2 10:01:06 UTC 2013


On Sun, Sep 1, 2013 at 7:13 PM, Nehal J Wani <nehaljw.kkd1 at gmail.com> wrote:
> Expose virDomainInterfaceAddresses to python binding
>
> examples/python/Makefile.am:
>   * Add new file domipaddrs.py
>
> examples/python/README:
>   * Add documentation for the python example
>
> python/libvirt-override-api.xml:
>   * Add new symbol for virDomainInterfaceAddresses
>
> python/libvirt-override.c:
>   * Hand written python api
>
> Example:
>   $ ./run python ./examples/python/domipaddrs.py f18
>   Interface  MAC address          Protocol     Address
>   lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
>   lo         00:00:00:00:00:00    ipv6         ::1/128
>   eth2       52:54:00:36:2a:e5
>   eth1       52:54:00:b1:70:19    ipv4         192.168.105.201/16
>   eth1       52:54:00:b1:70:19    ipv4         192.168.201.195/16
>   eth1       52:54:00:b1:70:19    ipv6         fe80::5054:ff:feb1:7019/64
>   eth0       52:54:00:2e:45:ce    ipv4         10.1.33.188/24
>   eth0       52:54:00:2e:45:ce    ipv6         2001:db8:0:f101::2/64
>   eth0       52:54:00:2e:45:ce    ipv6         fe80::5054:ff:fe2e:45ce/64
>
> ---
>  examples/python/Makefile.am     |   2 +-
>  examples/python/README          |   1 +
>  examples/python/domipaddrs.py   |  50 ++++++++++++++++++
>  python/libvirt-override-api.xml |   8 ++-
>  python/libvirt-override.c       | 111 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 170 insertions(+), 2 deletions(-)
>  create mode 100755 examples/python/domipaddrs.py
>
> diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am
> index 2cacfa1..d33ee17 100644
> --- a/examples/python/Makefile.am
> +++ b/examples/python/Makefile.am
> @@ -17,4 +17,4 @@
>  EXTRA_DIST=                                            \
>         README                                          \
>         consolecallback.py                              \
> -       dominfo.py domrestore.py domsave.py domstart.py esxlist.py
> +       dominfo.py domrestore.py domsave.py domstart.py esxlist.py domipaddrs.py
> diff --git a/examples/python/README b/examples/python/README
> index f4db76c..1285d52 100644
> --- a/examples/python/README
> +++ b/examples/python/README
> @@ -10,6 +10,7 @@ domsave.py  - save all running domU's into a directory
>  domrestore.py - restore domU's from their saved files in a directory
>  esxlist.py  - list active domains of an VMware ESX host and print some info.
>                also demonstrates how to use the libvirt.openAuth() method
> +domipaddrs.py - print domain interfaces along with their MAC and IP addresses
>
>  The XML files in this directory are examples of the XML format that libvirt
>  expects, and will have to be adapted for your setup. They are only needed
> diff --git a/examples/python/domipaddrs.py b/examples/python/domipaddrs.py
> new file mode 100755
> index 0000000..679e0bf
> --- /dev/null
> +++ b/examples/python/domipaddrs.py
> @@ -0,0 +1,50 @@
> +#!/usr/bin/env python
> +# domipaddrds - print domain interfaces along with their MAC and IP addresses
> +
> +import libvirt
> +import sys
> +
> +def usage():
> +    print "Usage: %s [URI] DOMAIN" % sys.argv[0]
> +    print "        Print domain interfaces along with their MAC and IP addresses"
> +
> +uri = None
> +name = None
> +args = len(sys.argv)
> +
> +if args == 2:
> +    name = sys.argv[1]
> +elif args == 3:
> +    uri = sys.argv[1]
> +    name = sys.argv[2]
> +else:
> +    usage()
> +    sys.exit(2)
> +
> +conn = libvirt.openReadOnly(uri)
> +if conn == None:
> +    print "Unable to open connection to libvirt"
> +    sys.exit(1)
> +
> +try:
> +    dom = conn.lookupByName(name)
> +except libvirt.libvirtError:
> +    print "Domain %s not found" % name
> +    sys.exit(0)
> +
> +ifaces = dom.interfaceAddresses(0)
> +if (ifaces == None):
> +    print "Failed to get domain interfaces"
> +    sys.exit(0)
> +
> +print " {0:10} {1:20} {2:12} {3}".format("Interface", "MAC address", "Protocol", "Address")
> +
> +for (name, val) in ifaces.iteritems():
> +    if val['ip_addrs']:
> +        for addr in val['ip_addrs']:
> +           print " {0:10} {1:19}".format(name, val['hwaddr']),
> +           print " {0:12} {1}/{2} ".format(addr['type'], addr['addr'], addr['prefix']),
> +           print
> +    else:
> +        print " {0:10} {1:19}".format(name, val['hwaddr']),
> +        print
> diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
> index 9a88215..60491de 100644
> --- a/python/libvirt-override-api.xml
> +++ b/python/libvirt-override-api.xml
> @@ -602,5 +602,11 @@
>        <arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
>        <arg name='flags' type='int' info='unused, pass 0'/>
>      </function>
> -  </symbols>
> +    <function name='virDomainInterfaceAddresses' file='python'>
> +      <info>returns a dictionary of domain interfaces along with their MAC and IP addresses</info>
> +      <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
> +      <arg name='flags' type='unsigned int' info='extra flags; not used yet, so callers should always pass 0'/>
> +      <return type='virDomainInterfacePtr' info="dictionary of domain interfaces along with their MAC and IP addresses"/>
> +    </function>
> +</symbols>
>  </api>
> diff --git a/python/libvirt-override.c b/python/libvirt-override.c
> index d16b9a2..67e0cb8 100644
> --- a/python/libvirt-override.c
> +++ b/python/libvirt-override.c
> @@ -4761,6 +4761,116 @@ cleanup:
>      return py_retval;
>  }
>
> +
> +static PyObject *
> +libvirt_virDomainInterfaceAddresses(PyObject *self ATTRIBUTE_UNUSED,
> +                                    PyObject *args)
> +{
> +    PyObject *py_retval = VIR_PY_NONE;
> +    virDomainPtr domain;
> +    PyObject *pyobj_domain;
> +    unsigned int flags;
> +    virDomainInterfacePtr *ifaces = NULL;
> +    int ifaces_count = 0;
> +    size_t i, j;
> +    int ret;
> +    bool full_free = true;
> +
> +    if (!PyArg_ParseTuple(args, (char *) "Oi:virDomainInterfacePtr",
> +                          &pyobj_domain, &flags))
> +        return NULL;
> +
> +    domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
> +
> +    LIBVIRT_BEGIN_ALLOW_THREADS;
> +    ifaces_count = virDomainInterfaceAddresses(domain, &ifaces, flags);
> +    ret = ifaces_count;
> +    LIBVIRT_END_ALLOW_THREADS;
> +    if (ret < 0)
> +        goto cleanup;
> +
> +    if (!(py_retval = PyDict_New()))
> +        goto no_memory;
> +
> +    for (i = 0; i < ifaces_count; i++) {
> +        virDomainInterfacePtr iface = ifaces[i];
> +        PyObject *py_ip_addrs = NULL;
> +        PyObject *py_iface = NULL;
> +
> +        if (!(py_iface = PyDict_New()))
> +            goto no_memory;
> +
> +        if (iface->naddrs) {
> +            if (!(py_ip_addrs = PyList_New(iface->naddrs))) {
> +                Py_DECREF(py_iface);
> +                goto no_memory;
> +            }
> +        } else {
> +            py_ip_addrs = VIR_PY_NONE;
> +        }
> +
> +        for (j = 0; j < iface->naddrs; j++) {
> +            virDomainIPAddressPtr ip_addr = &(iface->addrs[j]);
> +            PyObject *py_addr = PyDict_New();
> +            const char *type = NULL;
> +
> +            if (!py_addr) {
> +                Py_DECREF(py_iface);
> +                Py_DECREF(py_ip_addrs);
> +                goto no_memory;
> +            }
> +
> +            switch (ip_addr->type) {
> +            case VIR_IP_ADDR_TYPE_IPV4:
> +                type = "ipv4";
> +                break;
> +            case VIR_IP_ADDR_TYPE_IPV6:
> +                type = "ipv6";
> +                break;
> +            }
> +
> +            PyDict_SetItem(py_addr, libvirt_constcharPtrWrap("addr"),
> +                           PyString_FromString(ip_addr->addr));
> +            PyDict_SetItem(py_addr, libvirt_constcharPtrWrap("prefix"),
> +                           libvirt_intWrap(ip_addr->prefix));
> +            PyDict_SetItem(py_addr, libvirt_constcharPtrWrap("type"),
> +                           PyString_FromString(type));
> +
> +            PyList_SetItem(py_ip_addrs, j, py_addr);
> +        }
> +
> +        PyDict_SetItem(py_iface, libvirt_constcharPtrWrap("ip_addrs"),
> +                       py_ip_addrs);
> +        PyDict_SetItem(py_iface, libvirt_constcharPtrWrap("hwaddr"),
> +                       libvirt_charPtrWrap(iface->hwaddr));
> +
> +        PyDict_SetItem(py_retval, libvirt_charPtrWrap(iface->name),
> +                       py_iface);
> +    }
> +
> +    full_free = false;
> +
> +cleanup:
> +    if (ifaces) {
> +        for (i = 0; full_free && i < ifaces_count; i++) {
> +            /*
> +             * We don't want to free values we've just shared with python variables unless
> +             * there was an error and hence we are returning PY_NONE or equivalent
> +             */
> +            virDomainInterfaceFree(ifaces[i]);
> +        }
> +    }
> +    VIR_FREE(ifaces);
> +
> +    return py_retval;
> +
> +no_memory:
> +    Py_XDECREF(py_retval);
> +    py_retval = PyErr_NoMemory();
> +    goto cleanup;
> +}
> +
> +
>  /*******************************************
>   * Helper functions to avoid importing modules
>   * for every callback
> @@ -7284,6 +7394,7 @@ static PyMethodDef libvirtMethods[] = {
>      {(char *) "virDomainBlockPeek", libvirt_virDomainBlockPeek, METH_VARARGS, NULL},
>      {(char *) "virDomainMemoryPeek", libvirt_virDomainMemoryPeek, METH_VARARGS, NULL},
>      {(char *) "virDomainGetDiskErrors", libvirt_virDomainGetDiskErrors, METH_VARARGS, NULL},
> +    {(char *) "virDomainInterfaceAddresses", libvirt_virDomainInterfaceAddresses, METH_VARARGS, NULL},
>      {(char *) "virNodeGetMemoryParameters", libvirt_virNodeGetMemoryParameters, METH_VARARGS, NULL},
>      {(char *) "virNodeSetMemoryParameters", libvirt_virNodeSetMemoryParameters, METH_VARARGS, NULL},
>      {(char *) "virNodeGetCPUMap", libvirt_virNodeGetCPUMap, METH_VARARGS, NULL},
> --
> 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),
instead of string, the enum virIPAddrType is to be used in python, for which
examples/python/domipaddrs.py and python/libvirt-override.c are to be
modified a bit. Diff has been attached.

-- 
Nehal J Wani
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 5.diff
Type: application/octet-stream
Size: 2412 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20130902/dfd1e44d/attachment-0001.obj>


More information about the libvir-list mailing list