[libvirt] [PATCHv4 5/5] domifaddr: Expose python binding
Osier Yang
jyang at redhat.com
Tue Aug 27 11:37:41 UTC 2013
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 at redhat.com
>> https://www.redhat.com/mailman/listinfo/libvir-list
>>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
More information about the libvir-list
mailing list