On 25/08/13 14:02, Guido Günther wrote:
On Sun, Aug 25, 2013 at 04:45:45AM +0530, Nehal J Wani wrote:
> Expose virDomainInterfacesAddresses 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 virDomainInterfacesAddresses
>
> python/libvirt-override.c:
> * Hand written python api
>
> Example:
> $ ./run ./examples/python/domipaddrs.py qemu:///system f18
> Interface MAC address IPv4 Address IPv6 Address
> eth3:1 52:54:00:fe:4c:4f 192.168.101.198/24
> eth2:1 52:54:00:d3:39:ee 192.168.103.185/24
> eth2:0 52:54:00:d3:39:ee 192.168.103.184/24
> eth1:2 52:54:00:89:ad:35 192.168.102.143/24
> lo 00:00:00:00:00:00 127.0.0.1/8 ::1/128
> eth0:2 52:54:00:89:4e:97 192.168.101.132/24
> eth0:1 52:54:00:89:4e:97 192.168.101.133/24
> eth3 52:54:00:fe:4c:4f 192.168.101.197/24 fe80::5054:ff:fefe:4c4f/64
> eth2 52:54:00:d3:39:ee 192.168.103.183/24 fe80::5054:ff:fed3:39ee/64
> eth1 52:54:00:89:ad:35 192.168.102.142/24 fe80::5054:ff:fe89:ad35/64
> eth0 52:54:00:89:4e:97 192.168.101.130/24 fe80::5054:ff:fe89:4e97/64
>
> ---
> examples/python/Makefile.am | 2 +-
> examples/python/README | 1 +
> examples/python/domipaddrs.py | 49 +++++++++++++++++
> python/libvirt-override-api.xml | 8 ++-
> python/libvirt-override.c | 113 ++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 171 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..e71e8f6
> --- /dev/null
> +++ b/examples/python/domipaddrs.py
> @@ -0,0 +1,49 @@
> +#!/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.interfacesAddresses(0)
> +if (ifaces == None):
> + print "Failed to get domain interfaces"
> + sys.exit(0)
> +
> +print " {0:10} {1:20} {2:15} {3}".format("Interface",
"MAC address", "IPv4 Address", "IPv6 Address")
> +
> +for (name, val) in ifaces.iteritems():
> + print " {0:10} {1:17}".format(name, val['hwaddr']),
> +
> + if (val['ip_addrs'] <> None):
> + print " ",
> + for addr in val['ip_addrs']:
> + print "{0}/{1} ".format(addr['addr'],
addr['prefix']),
> + print
> diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
> index 9a88215..f5c6e83 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='virDomainInterfacesAddresses'
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..9eae9fb 100644
> --- a/python/libvirt-override.c
> +++ b/python/libvirt-override.c
> @@ -4761,6 +4761,118 @@ cleanup:
> return py_retval;
> }
>
> +
> +static PyObject *
> +libvirt_virDomainInterfacesAddresses(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 = virDomainInterfacesAddresses(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;
> +
> + 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";
I'd prefer to have libvirt.VIR_IP_ADDR_TYPE_IPV4 instead of a text
representation here but that's probably a matter of taste.
Agreed.
> + break;
> + case VIR_IP_ADDR_TYPE_IPV6:
> + type = "ipv6";
> + break
Same here.
> + default:
> + type = "unknown";
> + break;
Actually it's a dead branch, the api will fail as long as the ip address
type
is unkown. So simply removing the default branch is fine.
Same here.
> + }
> +
> + 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:
> + for (i = 0; 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
> + */
> + if (full_free)
> + virDomainInterfaceFree(ifaces[i]);
Wouldn't it be nicer to move the conditional outside the loop or even:
for (i = 0; full_free && i < ifaces_count; i++) {
Cheers,
-- Guido
> + }
> + 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 +7396,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 *) "virDomainInterfacesAddresses",
libvirt_virDomainInterfacesAddresses, 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
>
> --
> libvir-list mailing list
> libvir-list(a)redhat.com
>
https://www.redhat.com/mailman/listinfo/libvir-list
>
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list