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. > + break; > + case VIR_IP_ADDR_TYPE_IPV6: > + type = "ipv6"; > + break Same here. > + default: > + type = "unknown"; > + break; 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@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list