lxc.c revision 55c76589fd19e5f04697dcfd0084039cd77ef304
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * python-lxc: Python bindings for LXC
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * (C) Copyright Canonical Ltd. 2012-2013
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * Stéphane Graber <stgraber@ubuntu.com>
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * This library is free software; you can redistribute it and/or
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * modify it under the terms of the GNU Lesser General Public
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * License as published by the Free Software Foundation; either
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * version 2.1 of the License, or (at your option) any later version.
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * This library is distributed in the hope that it will be useful,
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * but WITHOUT ANY WARRANTY; without even the implied warranty of
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * Lesser General Public License for more details.
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * You should have received a copy of the GNU Lesser General Public
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * License along with this library; if not, write to the Free Software
250b1eec71b074acdff1c5f6b5a1f0d7d2c20b77Stéphane Graber * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Grabertypedef struct {
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graberconvert_tuple_to_char_pointer_array(PyObject *argv) {
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber /* not a list or tuple */
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber PyErr_SetString(PyExc_TypeError, "Expected list or tuple.");
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber char **result = (char**) calloc(argc + 1, sizeof(char*));
8128cf421081b683bca4610aa2db3e3ed851ab92KATOH Yasufumi for (i = 0; i < argc; i++) {
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber PyObject *pyobj = PySequence_Fast_GET_ITEM(argv, i);
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber PyErr_SetString(PyExc_ValueError, "Expected a string");
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber /* Maybe it wasn't UTF-8 encoded. An exception is already set. */
1bc07a5b8dbaef4b6eb6d30a260e9c2153ed368bKATOH Yasufumi /* Maybe pystr wasn't a valid object. An exception is already set.
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber /* We must make a copy of str, because it points into internal memory
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * which we do not own. Assume it's NULL terminated, otherwise we'd
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * have to use PyUnicode_AsUTF8AndSize() and be explicit about copying
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * the memory.
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber /* Do not decref pyobj since we stole a reference by using
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * PyTuple_GET_ITEM().
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber /* We can only iterate up to but not including i because malloc() does not
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * initialize its memory. Thus if we got here, i points to the index
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber * after the last strdup'd entry in result.
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber for (j = 0; j < i; j++)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber self = (Container *)type->tp_alloc(type, 0);
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_init(Container *self, PyObject *args, PyObject *kwds)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber static char *kwlist[] = {"name", "config_path", NULL};
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O&", kwlist,
8128cf421081b683bca4610aa2db3e3ed851ab92KATOH Yasufumi config_path = PyBytes_AS_STRING(fs_config_path);
8128cf421081b683bca4610aa2db3e3ed851ab92KATOH Yasufumi self->container = lxc_container_new(name, config_path);
8128cf421081b683bca4610aa2db3e3ed851ab92KATOH Yasufumi fprintf(stderr, "%d: error creating container %s\n", __LINE__, name);
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberLXC_get_default_config_path(PyObject *self, PyObject *args)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber return PyUnicode_FromString(lxc_get_default_config_path());
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberLXC_get_version(PyObject *self, PyObject *args)
1bc07a5b8dbaef4b6eb6d30a260e9c2153ed368bKATOH Yasufumi return PyUnicode_FromString(lxc_get_version());
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber// Container properties
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_config_file_name(Container *self, void *closure)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber self->container->config_file_name(self->container));
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_defined(Container *self, void *closure)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (self->container->is_defined(self->container)) {
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_init_pid(Container *self, void *closure)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber return PyLong_FromLong(self->container->init_pid(self->container));
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_name(Container *self, void *closure)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber return PyUnicode_FromString(self->container->name);
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_running(Container *self, void *closure)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (self->container->is_running(self->container)) {
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_state(Container *self, void *closure)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber return PyUnicode_FromString(self->container->state(self->container));
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber// Container Functions
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane GraberContainer_clear_config_item(Container *self, PyObject *args, PyObject *kwds)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (! PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist,
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (self->container->clear_config_item(self->container, key)) {
02e5d92b70562457a963f0803f0069053ce3292bChristian BraunerContainer_create(Container *self, PyObject *args, PyObject *kwds)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber static char *kwlist[] = {"template", "args", NULL};
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist,
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber create_args = convert_tuple_to_char_pointer_array(vargs);
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber PyErr_SetString(PyExc_ValueError, "args needs to be a tuple");
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if (self->container->create(self->container, template_name, NULL, NULL, 0, create_args))
if (vargs) {
return retval;
static PyObject *
static PyObject *
static PyObject *
int len = 0;
&key))
return NULL;
if (len < 0) {
return NULL;
return PyErr_NoMemory();
return NULL;
return ret;
static PyObject *
int len = 0;
&key))
return NULL;
if (len < 0) {
return NULL;
return PyErr_NoMemory();
return NULL;
return ret;
static PyObject *
return PyUnicode_FromString(
static PyObject *
int len = 0;
&key))
return NULL;
if (len < 0) {
return NULL;
return PyErr_NoMemory();
return NULL;
return ret;
static PyObject *
int scope = 0;
return NULL;
if (!ips)
return PyTuple_New(0);
while (ips[i])
if (!ret)
return NULL;
while (ips[i]) {
if (!unicode) {
while (ips[i]) {
return ret;
static PyObject *
return NULL;
static PyObject *
return NULL;
static PyObject *
return NULL;
static PyObject *
return NULL;
static PyObject *
&path))
return NULL;
static PyObject *
&timeout))
return NULL;
static PyObject *
int init_useinit = 0, i = 0;
return NULL;
if (!init_args) {
return NULL;
if (vargs) {
return retval;
static PyObject *
static PyObject *
static PyObject *
&escape))
return NULL;
static PyObject *
return NULL;
return NULL;
static PyObject *
return NULL;
struct lxc_attach_python_payload {
if (!result) {
PyErr_Print();
static char *kwlist[] = {"attach_flags", "namespaces", "personality", "initial_cwd", "uid", "gid", "env_policy", "extra_env_vars", "extra_keep_env", "stdin", "stdout", "stderr", NULL};
int temp_env_policy;
bool parse_result;
if (!options) {
return NULL;
if (!parse_result)
return NULL;
if (extra_env_vars_obj)
if (extra_keep_env_obj)
if (stdin_obj) {
return NULL;
if (stdout_obj) {
return NULL;
if (stderr_obj) {
return NULL;
return options;
if (!options)
static PyObject *
long ret;
return NULL;
return NULL;
if (!options)
return NULL;
if (ret < 0)
goto out;
if (wait) {
out:
static PyObject *
static PyObject *
static PyObject *
int rv;
static PyObject *
int i, rv;
return NULL;
return NULL;
return NULL;
NULL},
NULL},
NULL},
NULL},
NULL},
NULL},
PyInit__lxc(void)
PyObject* m;
PyObject* d;
return NULL;
if (m == NULL)
return NULL;
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "LXC_ATTACH_DROP_CAPABILITIES", PyLong_FromLong(LXC_ATTACH_DROP_CAPABILITIES));
PyDict_SetItemString(d, "LXC_ATTACH_REMOUNT_PROC_SYS", PyLong_FromLong(LXC_ATTACH_REMOUNT_PROC_SYS));