On Wed, Sep 18, 2013 at 02:53:33PM -0400, S.Çağlar Onur wrote: > Do you want me to sync this on top of staging and re-send?I think they are > conflicting right now.
Ah, if you don't mind, that'd be great (I started doing it but I'm getting interrupted quite a bit since I'm attending a conference)! > On Wed, Sep 18, 2013 at 2:47 PM, Stéphane Graber <stgra...@ubuntu.com>wrote: > > > 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 > > > > > > -- > S.Çağlar Onur <cag...@10ur.org> -- 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