On Mon, Sep 16, 2013 at 05:01:11PM -0400, S.Çağlar Onur wrote: > get_ips accepts an interface name as a parameter but there was no > way to get the interfaces names from the container. This patch > introduces a new get_interfaces call to the API so that users > can obtain the name of the interfaces. > > Support for python bindings also introduced as a part of this version. > > Signed-off-by: S.Çağlar Onur <cag...@10ur.org>
Acked-by: Stéphane Graber <stgra...@ubuntu.com> > --- > src/lxc/lxccontainer.c | 129 > ++++++++++++++++++++++++++---------- > src/lxc/lxccontainer.h | 3 + > src/lxc/utils.c | 22 +++++- > src/lxc/utils.h | 1 + > src/python-lxc/examples/api_test.py | 5 ++ > src/python-lxc/lxc.c | 60 +++++++++++++++-- > src/python-lxc/lxc/__init__.py | 8 +++ > 7 files changed, 189 insertions(+), 39 deletions(-) > > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index 79237df..8621cd8 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -1179,23 +1179,26 @@ static bool lxcapi_clear_config_item(struct > lxc_container *c, const char *key) > return ret == 0; > } > > -char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* > family, int scope) > -{ > - int count = 0; > - struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; > - char addressOutputBuffer[INET6_ADDRSTRLEN]; > - void *tempAddrPtr = NULL; > - char **addresses = NULL, **temp; > - char *address = NULL; > +static inline void exit_from_ns(struct lxc_container *c, int *old_netns, int > *new_netns) { > + /* Switch back to original netns */ > + if (*old_netns >= 0 && setns(*old_netns, CLONE_NEWNET)) > + SYSERROR("failed to setns"); > + if (*new_netns >= 0) > + close(*new_netns); > + if (*old_netns >= 0) > + close(*old_netns); > +} > + > +static inline bool enter_to_ns(struct lxc_container *c, int *old_netns, int > *new_netns) { > + int ret = 0; > char new_netns_path[MAXPATHLEN]; > - int old_netns = -1, new_netns = -1, ret = 0; > > if (!c->is_running(c)) > goto out; > > /* Save reference to old netns */ > - old_netns = open("/proc/self/ns/net", O_RDONLY); > - if (old_netns < 0) { > + *old_netns = open("/proc/self/ns/net", O_RDONLY); > + if (*old_netns < 0) { > SYSERROR("failed to open /proc/self/ns/net"); > goto out; > } > @@ -1205,16 +1208,91 @@ char** lxcapi_get_ips(struct lxc_container *c, char* > interface, char* family, in > if (ret < 0 || ret >= MAXPATHLEN) > goto out; > > - new_netns = open(new_netns_path, O_RDONLY); > - if (new_netns < 0) { > + *new_netns = open(new_netns_path, O_RDONLY); > + if (*new_netns < 0) { > SYSERROR("failed to open %s", new_netns_path); > goto out; > } > > - if (setns(new_netns, CLONE_NEWNET)) { > + if (setns(*new_netns, CLONE_NEWNET)) { > SYSERROR("failed to setns"); > goto out; > } > + return true; > +out: > + exit_from_ns(c, old_netns, new_netns); > + return false; > +} > + > +static char** lxcapi_get_interfaces(struct lxc_container *c) > +{ > + int count = 0, i; > + bool found = false; > + struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; > + char **interfaces = NULL, **temp; > + int old_netns = -1, new_netns = -1; > + > + if (!enter_to_ns(c, &old_netns, &new_netns)) > + goto out; > + > + /* Grab the list of interfaces */ > + if (getifaddrs(&interfaceArray)) { > + SYSERROR("failed to get interfaces list"); > + goto out; > + } > + > + /* Iterate through the interfaces */ > + for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = > tempIfAddr->ifa_next) { > + /* > + * WARNING: Following "for" loop does a linear search over the > interfaces array > + * For the containers with lots of interfaces this may be > problematic. > + * I'm not expecting this to be the common usage but if it turns out > to be > + * than using binary search or a hash table could be more > elegant solution. > + */ > + for (i = 0; i < count; i++) { > + if (strcmp(interfaces[i], tempIfAddr->ifa_name) == 0) { > + found = true; > + break; > + } > + } > + > + if (!found) { > + count += 1; > + temp = realloc(interfaces, count * sizeof(*interfaces)); > + if (!temp) { > + count -= 1; > + goto out; > + } > + interfaces = temp; > + interfaces[count - 1] = strdup(tempIfAddr->ifa_name); > + } > + found = false; > + } > + > +out: > + if (interfaceArray) > + freeifaddrs(interfaceArray); > + > + exit_from_ns(c, &old_netns, &new_netns); > + > + /* Append NULL to the array */ > + interfaces = (char **)lxc_append_null_to_array((void **)interfaces, > count); > + > + return interfaces; > +} > + > +static char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* > family, int scope) > +{ > + int count = 0; > + struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; > + char addressOutputBuffer[INET6_ADDRSTRLEN]; > + void *tempAddrPtr = NULL; > + char **addresses = NULL, **temp; > + char *address = NULL; > + int old_netns = -1, new_netns = -1; > + > + if (!enter_to_ns(c, &old_netns, &new_netns)) > + goto out; > > /* Grab the list of interfaces */ > if (getifaddrs(&interfaceArray)) { > @@ -1265,28 +1343,10 @@ out: > if(interfaceArray) > freeifaddrs(interfaceArray); > > - /* Switch back to original netns */ > - if (old_netns >= 0 && setns(old_netns, CLONE_NEWNET)) > - SYSERROR("failed to setns"); > - if (new_netns >= 0) > - close(new_netns); > - if (old_netns >= 0) > - close(old_netns); > + exit_from_ns(c, &old_netns, &new_netns); > > /* Append NULL to the array */ > - if (count) { > - count++; > - temp = realloc(addresses, count * sizeof(*addresses)); > - if (!temp) { > - int i; > - for (i = 0; i < count-1; i++) > - free(addresses[i]); > - free(addresses); > - return NULL; > - } > - addresses = temp; > - addresses[count - 1] = NULL; > - } > + addresses = (char **)lxc_append_null_to_array((void **)addresses, > count); > > return addresses; > } > @@ -2576,6 +2636,7 @@ struct lxc_container *lxc_container_new(const char > *name, const char *configpath > c->get_config_path = lxcapi_get_config_path; > c->set_config_path = lxcapi_set_config_path; > c->clone = lxcapi_clone; > + c->get_interfaces = lxcapi_get_interfaces; > c->get_ips = lxcapi_get_ips; > c->attach = lxcapi_attach; > c->attach_run_wait = lxcapi_attach_run_wait; > diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h > index f9ae43b..89b55bd 100644 > --- a/src/lxc/lxccontainer.h > +++ b/src/lxc/lxccontainer.h > @@ -90,6 +90,9 @@ struct lxc_container { > * the length which was our would be printed. */ > int (*get_config_item)(struct lxc_container *c, const char *key, char > *retv, int inlen); > int (*get_keys)(struct lxc_container *c, const char *key, char *retv, > int inlen); > + // Return interface names. The result is strdup()d, so free the result. > + char** (*get_interfaces)(struct lxc_container *c); > + // Return IP addresses. The result is strdup()d, so free the result. > char** (*get_ips)(struct lxc_container *c, char* interface, char* > family, int scope); > /* > * get_cgroup_item returns the number of bytes read, or an error (<0). > diff --git a/src/lxc/utils.c b/src/lxc/utils.c > index 78b234d..924cc19 100644 > --- a/src/lxc/utils.c > +++ b/src/lxc/utils.c > @@ -852,7 +852,7 @@ int lxc_write_to_file(const char *filename, const void* > buf, size_t count, bool > return -1; > ret = lxc_write_nointr(fd, buf, count); > if (ret < 0) > - goto out_error; > + goto out_error; > if ((size_t)ret != count) > goto out_error; > if (add_newline) { > @@ -899,3 +899,23 @@ int lxc_read_from_file(const char *filename, void* buf, > size_t count) > errno = saved_errno; > return ret; > } > + > +void **lxc_append_null_to_array(void **array, size_t count) > +{ > + void **temp; > + > + /* Append NULL to the array */ > + if (count) { > + temp = realloc(array, (count + 1) * sizeof(*array)); > + if (!temp) { > + int i; > + for (i = 0; i < count; i++) > + free(array[i]); > + free(array); > + return NULL; > + } > + array = temp; > + array[count] = NULL; > + } > + return array; > +} > diff --git a/src/lxc/utils.h b/src/lxc/utils.h > index ba7cfb3..55f98fa 100644 > --- a/src/lxc/utils.h > +++ b/src/lxc/utils.h > @@ -236,4 +236,5 @@ extern void lxc_free_array(void **array, lxc_free_fn > element_free_fn); > extern size_t lxc_array_len(void **array); > extern void **lxc_dup_array(void **array, lxc_dup_fn element_dup_fn, > lxc_free_fn element_free_fn); > > +extern void **lxc_append_null_to_array(void **array, size_t count); > #endif > diff --git a/src/python-lxc/examples/api_test.py > b/src/python-lxc/examples/api_test.py > index e078d2b..4754332 100644 > --- a/src/python-lxc/examples/api_test.py > +++ b/src/python-lxc/examples/api_test.py > @@ -89,6 +89,11 @@ assert(container.init_pid > 1) > assert(container.running) > assert(container.state == "RUNNING") > > + > +## Checking IP address > +print("Getting the interface names") > +assert(container.get_interfaces() == ('lo', 'eth0')) > + > ## Checking IP address > print("Getting the IP addresses") > > diff --git a/src/python-lxc/lxc.c b/src/python-lxc/lxc.c > index bd053a7..b6e0804 100644 > --- a/src/python-lxc/lxc.c > +++ b/src/python-lxc/lxc.c > @@ -411,6 +411,52 @@ Container_get_keys(Container *self, PyObject *args, > PyObject *kwds) > } > > static PyObject * > +Container_get_interfaces(Container *self) > +{ > + int i = 0; > + char** interfaces = NULL; > + > + PyObject* ret; > + > + /* Get the interfaces */ > + interfaces = self->container->get_interfaces(self->container); > + if (!interfaces) > + return PyTuple_New(0); > + > + /* Count the entries */ > + while (interfaces[i]) > + i++; > + > + /* Create the new tuple */ > + ret = PyTuple_New(i); > + if (!ret) > + return NULL; > + > + /* Add the entries to the tuple and free the memory */ > + i = 0; > + while (interfaces[i]) { > + PyObject *unicode = PyUnicode_FromString(interfaces[i]); > + if (!unicode) { > + Py_DECREF(ret); > + ret = NULL; > + break; > + } > + PyTuple_SET_ITEM(ret, i, unicode); > + i++; > + } > + > + /* Free the list of IPs */ > + i = 0; > + while (interfaces[i]) { > + free(interfaces[i]); > + i++; > + } > + free(interfaces); > + > + return ret; > +} > + > +static PyObject * > Container_get_ips(Container *self, PyObject *args, PyObject *kwds) > { > static char *kwlist[] = {"interface", "family", "scope", NULL}; > @@ -898,15 +944,15 @@ LXC_arch_to_personality(PyObject *self, PyObject *arg) > PyErr_SetString(PyExc_ValueError, "Expected a string"); > return NULL; > } > - > + > pystr = PyUnicode_AsUTF8String(arg); > if (!pystr) > return NULL; > - > + > str = PyBytes_AsString(pystr); > if (!str) > goto out; > - > + > rv = lxc_config_parse_arch(str); > if (rv == -1) > PyErr_SetString(PyExc_KeyError, "Failed to lookup architecture."); > @@ -1025,6 +1071,12 @@ static PyMethodDef Container_methods[] = { > "\n" > "Get a list of valid sub-keys for a key." > }, > + {"get_interfaces", (PyCFunction)Container_get_interfaces, > + METH_NOARGS, > + "get_interface() -> tuple\n" > + "\n" > + "Get a tuple of interfaces for the container." > + }, > {"get_ips", (PyCFunction)Container_get_ips, > METH_VARARGS|METH_KEYWORDS, > "get_ips(interface, family, scope) -> tuple\n" > @@ -1205,7 +1257,7 @@ PyInit__lxc(void) > > /* add constants */ > d = PyModule_GetDict(m); > - > + > #define PYLXC_EXPORT_CONST(c) PyDict_SetItemString(d, #c, > PyLong_FromLong(c)) > > /* environment variable handling */ > diff --git a/src/python-lxc/lxc/__init__.py b/src/python-lxc/lxc/__init__.py > index 3fb76dc..6a29903 100644 > --- a/src/python-lxc/lxc/__init__.py > +++ b/src/python-lxc/lxc/__init__.py > @@ -333,6 +333,14 @@ class Container(_lxc.Container): > else: > return value > > + def get_interfaces(self): > + """ > + Get a tuple of interfaces for the container. > + """ > + > + return _lxc.Container.get_interfaces(self) > + > + > def get_ips(self, interface=None, family=None, scope=None, timeout=0): > """ > Get a tuple of IPs for the container. > -- > 1.8.1.2 > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > _______________________________________________ > Lxc-devel mailing list > Lxc-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/lxc-devel -- Stéphane Graber Ubuntu developer http://www.ubuntu.com
signature.asc
Description: Digital signature
------------------------------------------------------------------------------ LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel