[libvirt] [PATCH python v10] Expose virDomainInterfacesAddresses to python binding

Daniel P. Berrange berrange at redhat.com
Mon Mar 16 14:55:56 UTC 2015


From: Nehal J Wani <nehaljw.kkd1 at gmail.com>

examples/Makefile.am:
  * Add new file domipaddrs.py

examples/README:
  * Add documentation for the python example

libvirt-override-api.xml:
  * Add new symbol for virDomainInterfacesAddresses

libvirt-override.c:
  * Hand written python api

Example:
  $ python examples/domipaddrs.py qemu:///system 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
    eth3       52:54:00:20:70:3d    ipv4         192.168.105.240/16
    eth3       52:54:00:20:70:3d    ipv6         fe80::5054:ff:fe20:703d/64
    eth2       52:54:00:36:2a:e5    N/A          N/A
    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
---
 MANIFEST.in              |   1 +
 examples/README          |   1 +
 examples/domipaddrs.py   |  57 +++++++++++++++++++++++++
 generator.py             |   2 +
 libvirt-override-api.xml |   9 +++-
 libvirt-override.c       | 105 +++++++++++++++++++++++++++++++++++++++++++++++
 sanitytest.py            |   3 ++
 7 files changed, 177 insertions(+), 1 deletion(-)
 create mode 100755 examples/domipaddrs.py

diff --git a/MANIFEST.in b/MANIFEST.in
index d7bc545..dd05221 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,6 +4,7 @@ include COPYING
 include COPYING.LESSER
 include ChangeLog
 include examples/consolecallback.py
+include examples/domipaddrs.py
 include examples/dominfo.py
 include examples/domrestore.py
 include examples/domsave.py
diff --git a/examples/README b/examples/README
index 5b5d405..1d4b425 100644
--- a/examples/README
+++ b/examples/README
@@ -11,6 +11,7 @@ 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
 dhcpleases.py - list dhcp leases for a given virtual network
+domipaddrs.py - list IP addresses for guest domains
 
 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/domipaddrs.py b/examples/domipaddrs.py
new file mode 100755
index 0000000..d6d5cac
--- /dev/null
+++ b/examples/domipaddrs.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# domipaddrs - 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.open(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(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE);
+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")
+
+def toIPAddrType(addrType):
+    if addrType == libvirt.VIR_IP_ADDR_TYPE_IPV4:
+        return "ipv4"
+    elif addrType == libvirt.VIR_IP_ADDR_TYPE_IPV6:
+        return "ipv6"
+
+for (name, val) in ifaces.iteritems():
+    if val['addrs']:
+        for addr in val['addrs']:
+           print " {0:10} {1:19}".format(name, val['hwaddr']),
+           print " {0:12} {1}/{2} ".format(toIPAddrType(addr['type']), addr['addr'], addr['prefix']),
+           print
+    else:
+        print " {0:10} {1:19}".format(name, val['hwaddr']),
+        print " {0:12} {1}".format("N/A", "N/A"),
+        print
diff --git a/generator.py b/generator.py
index df7a74d..8c1c48e 100755
--- a/generator.py
+++ b/generator.py
@@ -483,6 +483,7 @@ skip_impl = (
     'virDomainBlockCopy',
     'virNodeAllocPages',
     'virDomainGetFSInfo',
+    'virDomainInterfaceAddresses',
 )
 
 lxc_skip_impl = (
@@ -595,6 +596,7 @@ skip_function = (
     'virDomainStatsRecordListFree', # only useful in C, python uses dict
     'virDomainFSInfoFree', # only useful in C, python code uses list
     'virDomainIOThreadsInfoFree', # only useful in C, python code uses list
+    'virDomainInterfaceFree', # only useful in C, python code uses list
 )
 
 lxc_skip_function = (
diff --git a/libvirt-override-api.xml b/libvirt-override-api.xml
index 4660c9f..b197639 100644
--- a/libvirt-override-api.xml
+++ b/libvirt-override-api.xml
@@ -678,5 +678,12 @@
       <arg name='flags' type='unsigned int' info='unused, pass 0'/>
       <return type='char *' info="list of mounted filesystems information"/>
     </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='source' type='unsigned int' info='the data source'/>
+      <arg name='flags' type='unsigned int' info='extra flags; not used yet, so callers should always pass 0'/>
+      <return type='char *' info="dictionary of domain interfaces along with their MAC and IP addresses"/>
+    </function>
+</symbols>
 </api>
diff --git a/libvirt-override.c b/libvirt-override.c
index 1241305..bf3cb70 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -5120,6 +5120,108 @@ 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 source;
+    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 *) "Oii:virDomainInterfacePtr",
+                          &pyobj_domain, &source, &flags))
+        return NULL;
+
+    domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    ifaces_count = virDomainInterfaceAddresses(domain, &ifaces, source, 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_addrs = NULL;
+        PyObject *py_iface = NULL;
+
+        if (!(py_iface = PyDict_New()))
+            goto no_memory;
+
+        if (iface->naddrs) {
+            if (!(py_addrs = PyList_New(iface->naddrs))) {
+                Py_DECREF(py_iface);
+                goto no_memory;
+            }
+        } else {
+            py_addrs = VIR_PY_NONE;
+        }
+
+        for (j = 0; j < iface->naddrs; j++) {
+            virDomainIPAddressPtr addr = &(iface->addrs[j]);
+            PyObject *py_addr = PyDict_New();
+            int type = addr->type;
+
+            if (!addr) {
+                Py_DECREF(py_iface);
+                Py_DECREF(py_addrs);
+                goto no_memory;
+            }
+
+            PyDict_SetItem(py_addr, libvirt_constcharPtrWrap("addr"),
+                          libvirt_constcharPtrWrap(addr->addr));
+            PyDict_SetItem(py_addr, libvirt_constcharPtrWrap("prefix"),
+                           libvirt_intWrap(addr->prefix));
+            PyDict_SetItem(py_addr, libvirt_constcharPtrWrap("type"),
+                           libvirt_intWrap(type));
+
+            PyList_SetItem(py_addrs, j, py_addr);
+        }
+
+        PyDict_SetItem(py_iface, libvirt_constcharPtrWrap("addrs"),
+                       py_addrs);
+        PyDict_SetItem(py_iface, libvirt_constcharPtrWrap("hwaddr"),
+                       libvirt_constcharPtrWrap(iface->hwaddr));
+
+        PyDict_SetItem(py_retval, libvirt_charPtrWrap(iface->name),
+                       py_iface);
+    }
+
+    full_free = false;
+
+cleanup:
+    if (ifaces && ifaces_count > 0) {
+        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
@@ -8750,6 +8852,9 @@ static PyMethodDef libvirtMethods[] = {
 #if LIBVIR_CHECK_VERSION(1, 2, 11)
     {(char *) "virDomainGetFSInfo", libvirt_virDomainGetFSInfo, METH_VARARGS, NULL},
 #endif /* LIBVIR_CHECK_VERSION(1, 2, 11) */
+#if LIBVIR_CHECK_VERSION(1, 2, 14)
+    {(char *) "virDomainInterfaceAddresses", libvirt_virDomainInterfaceAddresses, METH_VARARGS, NULL},
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 14) */
     {NULL, NULL, 0, NULL}
 };
 
diff --git a/sanitytest.py b/sanitytest.py
index 0e6e0e5..2b609a9 100644
--- a/sanitytest.py
+++ b/sanitytest.py
@@ -145,6 +145,9 @@ for cname in wantfunctions:
     if name[0:26] == "virDomainIOThreadsInfoFree":
         continue
 
+    if name[0:33] == "virDomainInterfaceFree":
+        continue
+
     if name[0:21] == "virDomainListGetStats":
         name = "virConnectDomainListGetStats"
 
-- 
2.1.0




More information about the libvir-list mailing list