2 * python-lxc: Python bindings for LXC
4 * (C) Copyright Canonical Ltd. 2012-2013
7 * Stéphane Graber <stgraber@ubuntu.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
26 #include "structmember.h"
27 #include <lxc/lxccontainer.h>
33 * CLONE_* definitions copied from lxc/namespace.h
36 # define CLONE_FS 0x00000200
39 # define CLONE_NEWNS 0x00020000
41 #ifndef CLONE_NEWCGROUP
42 # define CLONE_NEWCGROUP 0x02000000
45 # define CLONE_NEWUTS 0x04000000
48 # define CLONE_NEWIPC 0x08000000
51 # define CLONE_NEWUSER 0x10000000
54 # define CLONE_NEWPID 0x20000000
57 # define CLONE_NEWNET 0x40000000
60 /* From sys/personality.h */
61 #define PER_LINUX 0x0000
62 #define PER_LINUX32 0x0008
64 /* Helper functions */
66 /* Copied from lxc/utils.c */
67 static int lxc_wait_for_pid_status(pid_t pid
)
72 ret
= waitpid(pid
, &status
, 0);
83 /* Copied from lxc/confile.c, with HAVE_SYS_PERSONALITY_H check removed */
84 signed long lxc_config_parse_arch(const char *arch
)
90 { "x86", PER_LINUX32
},
91 { "linux32", PER_LINUX32
},
92 { "i386", PER_LINUX32
},
93 { "i486", PER_LINUX32
},
94 { "i586", PER_LINUX32
},
95 { "i686", PER_LINUX32
},
96 { "athlon", PER_LINUX32
},
97 { "linux64", PER_LINUX
},
98 { "x86_64", PER_LINUX
},
99 { "amd64", PER_LINUX
},
101 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
105 for (i
= 0; i
< len
; i
++) {
106 if (!strcmp(pername
[i
].name
, arch
))
107 return pername
[i
].per
;
114 convert_tuple_to_char_pointer_array(PyObject
*argv
) {
119 /* not a list or tuple */
120 if (!PyList_Check(argv
) && !PyTuple_Check(argv
)) {
121 PyErr_SetString(PyExc_TypeError
, "Expected list or tuple.");
125 argc
= PySequence_Fast_GET_SIZE(argv
);
127 result
= (char**) calloc(argc
+ 1, sizeof(char*));
129 if (result
== NULL
) {
130 PyErr_SetNone(PyExc_MemoryError
);
134 for (i
= 0; i
< argc
; i
++) {
136 PyObject
*pystr
= NULL
;
137 PyObject
*pyobj
= PySequence_Fast_GET_ITEM(argv
, i
);
138 assert(pyobj
!= NULL
);
140 if (!PyUnicode_Check(pyobj
)) {
141 PyErr_SetString(PyExc_ValueError
, "Expected a string");
145 pystr
= PyUnicode_AsUTF8String(pyobj
);
147 /* Maybe it wasn't UTF-8 encoded. An exception is already set. */
151 str
= PyBytes_AsString(pystr
);
153 /* Maybe pystr wasn't a valid object. An exception is already set.
159 /* We must make a copy of str, because it points into internal memory
160 * which we do not own. Assume it's NULL terminated, otherwise we'd
161 * have to use PyUnicode_AsUTF8AndSize() and be explicit about copying
164 result
[i
] = strdup(str
);
166 /* Do not decref pyobj since we stole a reference by using
167 * PyTuple_GET_ITEM().
170 if (result
[i
] == NULL
) {
171 PyErr_SetNone(PyExc_MemoryError
);
180 /* We can only iterate up to but not including i because malloc() does not
181 * initialize its memory. Thus if we got here, i points to the index
182 * after the last strdup'd entry in result.
184 for (j
= 0; j
< i
; j
++)
190 struct lxc_attach_python_payload
{
195 static int lxc_attach_python_exec(void* _payload
)
197 /* This function is the first one to be called after attaching to a
198 * container. As lxc_attach() calls fork() PyOS_AfterFork should be called
199 * in the new process if the Python interpreter will continue to be used.
203 struct lxc_attach_python_payload
*payload
=
204 (struct lxc_attach_python_payload
*)_payload
;
205 PyObject
*result
= PyObject_CallFunctionObjArgs(payload
->fn
,
212 if (PyLong_Check(result
))
213 return (int)PyLong_AsLong(result
);
218 static void lxc_attach_free_options(lxc_attach_options_t
*options
);
220 static lxc_attach_options_t
*lxc_attach_parse_options(PyObject
*kwds
)
222 static char *kwlist
[] = {"attach_flags", "namespaces", "personality",
223 "initial_cwd", "uid", "gid", "env_policy",
224 "extra_env_vars", "extra_keep_env", "stdin",
225 "stdout", "stderr", NULL
};
226 long temp_uid
, temp_gid
;
228 PyObject
*extra_env_vars_obj
= NULL
;
229 PyObject
*extra_keep_env_obj
= NULL
;
230 PyObject
*stdin_obj
= NULL
;
231 PyObject
*stdout_obj
= NULL
;
232 PyObject
*stderr_obj
= NULL
;
233 PyObject
*initial_cwd_obj
= NULL
;
234 PyObject
*dummy
= NULL
;
237 lxc_attach_options_t default_options
= LXC_ATTACH_OPTIONS_DEFAULT
;
238 lxc_attach_options_t
*options
= malloc(sizeof(*options
));
241 PyErr_SetNone(PyExc_MemoryError
);
244 memcpy(options
, &default_options
, sizeof(*options
));
246 /* we need some dummy variables because we can't be sure
247 * the data types match completely */
250 temp_env_policy
= options
->env_policy
;
252 /* we need a dummy tuple */
253 dummy
= PyTuple_New(0);
255 parse_result
= PyArg_ParseTupleAndKeywords(dummy
, kwds
, "|iilO&lliOOOOO",
256 kwlist
, &options
->attach_flags
,
257 &options
->namespaces
,
258 &options
->personality
,
259 PyUnicode_FSConverter
,
260 &initial_cwd_obj
, &temp_uid
,
261 &temp_gid
, &temp_env_policy
,
264 &stdin_obj
, &stdout_obj
,
267 /* immediately get rid of the dummy tuple */
271 lxc_attach_free_options(options
);
275 /* duplicate the string, so we don't depend on some random Python object */
276 if (initial_cwd_obj
!= NULL
) {
277 options
->initial_cwd
= strndup(PyBytes_AsString(initial_cwd_obj
),
278 PyBytes_Size(initial_cwd_obj
));
279 Py_DECREF(initial_cwd_obj
);
282 /* do the type conversion from the types that match the parse string */
283 if (temp_uid
!= -1) options
->uid
= (uid_t
)temp_uid
;
284 if (temp_gid
!= -1) options
->gid
= (gid_t
)temp_gid
;
285 options
->env_policy
= (lxc_attach_env_policy_t
)temp_env_policy
;
287 if (extra_env_vars_obj
)
288 options
->extra_env_vars
=
289 convert_tuple_to_char_pointer_array(extra_env_vars_obj
);
290 if (extra_keep_env_obj
)
291 options
->extra_keep_env
=
292 convert_tuple_to_char_pointer_array(extra_keep_env_obj
);
294 options
->stdin_fd
= PyObject_AsFileDescriptor(stdin_obj
);
295 if (options
->stdin_fd
< 0) {
296 lxc_attach_free_options(options
);
301 options
->stdout_fd
= PyObject_AsFileDescriptor(stdout_obj
);
302 if (options
->stdout_fd
< 0) {
303 lxc_attach_free_options(options
);
308 options
->stderr_fd
= PyObject_AsFileDescriptor(stderr_obj
);
309 if (options
->stderr_fd
< 0) {
310 lxc_attach_free_options(options
);
318 void lxc_attach_free_options(lxc_attach_options_t
*options
)
323 free(options
->initial_cwd
);
324 if (options
->extra_env_vars
) {
325 for (i
= 0; options
->extra_env_vars
[i
]; i
++)
326 free(options
->extra_env_vars
[i
]);
327 free(options
->extra_env_vars
);
329 if (options
->extra_keep_env
) {
330 for (i
= 0; options
->extra_keep_env
[i
]; i
++)
331 free(options
->extra_keep_env
[i
]);
332 free(options
->extra_keep_env
);
337 /* Module functions */
339 LXC_arch_to_personality(PyObject
*self
, PyObject
*arg
)
342 PyObject
*pystr
= NULL
;
345 if (!PyUnicode_Check(arg
)) {
346 PyErr_SetString(PyExc_ValueError
, "Expected a string");
350 pystr
= PyUnicode_AsUTF8String(arg
);
354 str
= PyBytes_AsString(pystr
);
358 rv
= lxc_config_parse_arch(str
);
360 PyErr_SetString(PyExc_KeyError
, "Failed to lookup architecture.");
364 return rv
== -1 ? NULL
: PyLong_FromLong(rv
);
368 LXC_attach_run_command(PyObject
*self
, PyObject
*arg
)
370 PyObject
*args_obj
= NULL
;
372 lxc_attach_command_t cmd
= {
377 if (!PyArg_ParseTuple(arg
, "sO", (const char**)&cmd
.program
, &args_obj
))
379 if (args_obj
&& PyList_Check(args_obj
)) {
380 cmd
.argv
= convert_tuple_to_char_pointer_array(args_obj
);
382 PyErr_Format(PyExc_TypeError
, "Second part of tuple passed to "
383 "attach_run_command must be a list.");
390 rv
= lxc_attach_run_command(&cmd
);
392 for (i
= 0; cmd
.argv
[i
]; i
++)
396 return PyLong_FromLong(rv
);
400 LXC_attach_run_shell(PyObject
*self
, PyObject
*arg
)
404 rv
= lxc_attach_run_shell(NULL
);
406 return PyLong_FromLong(rv
);
410 LXC_get_global_config_item(PyObject
*self
, PyObject
*args
, PyObject
*kwds
)
412 static char *kwlist
[] = {"key", NULL
};
414 const char* value
= NULL
;
416 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|", kwlist
,
420 value
= lxc_get_global_config_item(key
);
423 PyErr_SetString(PyExc_KeyError
, "Invalid configuration key");
427 return PyUnicode_FromString(value
);
431 LXC_get_version(PyObject
*self
, PyObject
*args
)
433 return PyUnicode_FromString(lxc_get_version());
437 LXC_list_containers(PyObject
*self
, PyObject
*args
, PyObject
*kwds
)
440 PyObject
*list
= NULL
;
444 int list_defined
= 1;
446 PyObject
*py_list_active
= NULL
;
447 PyObject
*py_list_defined
= NULL
;
449 char* config_path
= NULL
;
452 PyObject
*vargs
= NULL
;
453 static char *kwlist
[] = {"active", "defined", "config_path", NULL
};
455 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|OOs", kwlist
,
458 &config_path
, &vargs
))
461 /* We default to listing everything */
462 if (py_list_active
&& py_list_active
!= Py_True
) {
466 if (py_list_defined
&& py_list_defined
!= Py_True
) {
470 /* Call the right API function based on filters */
471 if (list_active
== 1 && list_defined
== 1)
472 list_count
= list_all_containers(config_path
, &names
, NULL
);
473 else if (list_active
== 1)
474 list_count
= list_active_containers(config_path
, &names
, NULL
);
475 else if (list_defined
== 1)
476 list_count
= list_defined_containers(config_path
, &names
, NULL
);
479 if (list_count
< 0) {
480 PyErr_SetString(PyExc_ValueError
, "failure to list containers");
484 /* Generate the tuple */
485 list
= PyTuple_New(list_count
);
486 for (i
= 0; i
< list_count
; i
++) {
487 PyTuple_SET_ITEM(list
, i
, PyUnicode_FromString(names
[i
]));
495 /* Base type and functions for Container */
498 struct lxc_container
*container
;
502 Container_dealloc(Container
* self
)
504 lxc_container_put(self
->container
);
505 Py_TYPE(self
)->tp_free((PyObject
*)self
);
509 Container_init(Container
*self
, PyObject
*args
, PyObject
*kwds
)
511 static char *kwlist
[] = {"name", "config_path", NULL
};
513 PyObject
*fs_config_path
= NULL
;
514 char *config_path
= NULL
;
516 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|O&", kwlist
,
518 PyUnicode_FSConverter
, &fs_config_path
))
521 if (fs_config_path
!= NULL
) {
522 config_path
= PyBytes_AS_STRING(fs_config_path
);
523 assert(config_path
!= NULL
);
526 self
->container
= lxc_container_new(name
, config_path
);
527 if (!self
->container
) {
528 Py_XDECREF(fs_config_path
);
530 PyErr_Format(PyExc_RuntimeError
, "%s:%s:%d: error during init for container '%s'.",
531 __FUNCTION__
, __FILE__
, __LINE__
, name
);
535 Py_XDECREF(fs_config_path
);
540 Container_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
544 self
= (Container
*)type
->tp_alloc(type
, 0);
546 return (PyObject
*)self
;
549 /* Container properties */
551 Container_config_file_name(Container
*self
, void *closure
)
553 return PyUnicode_FromString(
554 self
->container
->config_file_name(self
->container
));
558 Container_controllable(Container
*self
, void *closure
)
560 if (self
->container
->may_control(self
->container
)) {
568 Container_defined(Container
*self
, void *closure
)
570 if (self
->container
->is_defined(self
->container
)) {
578 Container_init_pid(Container
*self
, void *closure
)
580 return PyLong_FromLong(self
->container
->init_pid(self
->container
));
584 Container_name(Container
*self
, void *closure
)
586 return PyUnicode_FromString(self
->container
->name
);
590 Container_running(Container
*self
, void *closure
)
592 if (self
->container
->is_running(self
->container
)) {
600 Container_state(Container
*self
, void *closure
)
602 return PyUnicode_FromString(self
->container
->state(self
->container
));
605 /* Container Functions */
607 Container_attach_interface(Container
*self
, PyObject
*args
, PyObject
*kwds
)
609 static char *kwlist
[] = {"src_ifname", "dst_ifname", NULL
};
610 char *src_name
= NULL
;
611 char *dst_name
= NULL
;
612 PyObject
*py_src_name
= NULL
;
613 PyObject
*py_dst_name
= NULL
;
615 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "O&|O&", kwlist
,
616 PyUnicode_FSConverter
, &py_src_name
,
617 PyUnicode_FSConverter
, &py_dst_name
))
620 if (py_src_name
!= NULL
) {
621 src_name
= PyBytes_AS_STRING(py_src_name
);
622 assert(src_name
!= NULL
);
625 if (py_dst_name
!= NULL
) {
626 dst_name
= PyBytes_AS_STRING(py_dst_name
);
627 assert(dst_name
!= NULL
);
630 if (self
->container
->attach_interface(self
->container
, src_name
, dst_name
)) {
631 Py_XDECREF(py_src_name
);
632 Py_XDECREF(py_dst_name
);
636 Py_XDECREF(py_src_name
);
637 Py_XDECREF(py_dst_name
);
642 Container_detach_interface(Container
*self
, PyObject
*args
, PyObject
*kwds
)
644 static char *kwlist
[] = {"ifname", NULL
};
646 PyObject
*py_ifname
= NULL
;
648 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "O&", kwlist
,
649 PyUnicode_FSConverter
, &py_ifname
))
652 if (py_ifname
!= NULL
) {
653 ifname
= PyBytes_AS_STRING(py_ifname
);
654 assert(ifname
!= NULL
);
657 if (self
->container
->detach_interface(self
->container
, ifname
, NULL
)) {
658 Py_XDECREF(py_ifname
);
662 Py_XDECREF(py_ifname
);
667 Container_add_device_node(Container
*self
, PyObject
*args
, PyObject
*kwds
)
669 static char *kwlist
[] = {"src_path", "dest_path", NULL
};
670 char *src_path
= NULL
;
671 char *dst_path
= NULL
;
672 PyObject
*py_src_path
= NULL
;
673 PyObject
*py_dst_path
= NULL
;
675 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "O&|O&", kwlist
,
676 PyUnicode_FSConverter
, &py_src_path
,
677 PyUnicode_FSConverter
, &py_dst_path
))
680 if (py_src_path
!= NULL
) {
681 src_path
= PyBytes_AS_STRING(py_src_path
);
682 assert(src_path
!= NULL
);
685 if (py_dst_path
!= NULL
) {
686 dst_path
= PyBytes_AS_STRING(py_dst_path
);
687 assert(dst_path
!= NULL
);
690 if (self
->container
->add_device_node(self
->container
, src_path
,
692 Py_XDECREF(py_src_path
);
693 Py_XDECREF(py_dst_path
);
697 Py_XDECREF(py_src_path
);
698 Py_XDECREF(py_dst_path
);
703 Container_attach_and_possibly_wait(Container
*self
, PyObject
*args
,
704 PyObject
*kwds
, int wait
)
706 struct lxc_attach_python_payload payload
= { NULL
, NULL
};
707 lxc_attach_options_t
*options
= NULL
;
711 if (!PyArg_ParseTuple(args
, "O|O", &payload
.fn
, &payload
.arg
))
713 if (!PyCallable_Check(payload
.fn
)) {
714 PyErr_Format(PyExc_TypeError
, "attach: object not callable");
718 options
= lxc_attach_parse_options(kwds
);
722 ret
= self
->container
->attach(self
->container
, lxc_attach_python_exec
,
723 &payload
, options
, &pid
);
728 Py_BEGIN_ALLOW_THREADS
729 ret
= lxc_wait_for_pid_status(pid
);
731 /* handle case where attach fails */
732 if (WIFEXITED(ret
) && WEXITSTATUS(ret
) == 255)
739 lxc_attach_free_options(options
);
740 return PyLong_FromLong(ret
);
744 Container_attach(Container
*self
, PyObject
*args
, PyObject
*kwds
)
746 return Container_attach_and_possibly_wait(self
, args
, kwds
, 0);
750 Container_attach_wait(Container
*self
, PyObject
*args
, PyObject
*kwds
)
752 return Container_attach_and_possibly_wait(self
, args
, kwds
, 1);
756 Container_clear_config(Container
*self
, PyObject
*args
, PyObject
*kwds
)
758 self
->container
->clear_config(self
->container
);
764 Container_clear_config_item(Container
*self
, PyObject
*args
, PyObject
*kwds
)
766 static char *kwlist
[] = {"key", NULL
};
769 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s", kwlist
,
773 if (self
->container
->clear_config_item(self
->container
, key
)) {
781 Container_clone(Container
*self
, PyObject
*args
, PyObject
*kwds
)
783 char *newname
= NULL
;
784 char *config_path
= NULL
;
786 char *bdevtype
= NULL
;
787 char *bdevdata
= NULL
;
788 unsigned long newsize
= 0;
789 char **hookargs
= NULL
;
791 PyObject
*py_hookargs
= NULL
;
792 PyObject
*py_config_path
= NULL
;
793 struct lxc_container
*new_container
= NULL
;
796 static char *kwlist
[] = {"newname", "config_path", "flags", "bdevtype",
797 "bdevdata", "newsize", "hookargs", NULL
};
798 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|O&isskO", kwlist
,
800 PyUnicode_FSConverter
, &py_config_path
,
801 &flags
, &bdevtype
, &bdevdata
, &newsize
,
806 if (PyTuple_Check(py_hookargs
)) {
807 hookargs
= convert_tuple_to_char_pointer_array(py_hookargs
);
813 PyErr_SetString(PyExc_ValueError
, "hookargs needs to be a tuple");
818 if (py_config_path
!= NULL
) {
819 config_path
= PyBytes_AS_STRING(py_config_path
);
820 assert(config_path
!= NULL
);
823 new_container
= self
->container
->clone(self
->container
, newname
,
824 config_path
, flags
, bdevtype
,
825 bdevdata
, newsize
, hookargs
);
827 Py_XDECREF(py_config_path
);
830 for (i
= 0; i
< PyTuple_GET_SIZE(py_hookargs
); i
++)
835 if (new_container
== NULL
) {
839 lxc_container_put(new_container
);
845 Container_console(Container
*self
, PyObject
*args
, PyObject
*kwds
)
847 static char *kwlist
[] = {"ttynum", "stdinfd", "stdoutfd", "stderrfd",
849 int ttynum
= -1, stdinfd
= 0, stdoutfd
= 1, stderrfd
= 2, escape
= 1;
851 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|iiiii", kwlist
,
852 &ttynum
, &stdinfd
, &stdoutfd
, &stderrfd
,
856 if (self
->container
->console(self
->container
, ttynum
,
857 stdinfd
, stdoutfd
, stderrfd
, escape
) == 0) {
864 Container_console_getfd(Container
*self
, PyObject
*args
, PyObject
*kwds
)
866 static char *kwlist
[] = {"ttynum", NULL
};
867 int ttynum
= -1, masterfd
;
869 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|i", kwlist
, &ttynum
))
872 if (self
->container
->console_getfd(self
->container
, &ttynum
,
874 PyErr_SetString(PyExc_ValueError
, "Unable to allocate tty");
877 return PyLong_FromLong(masterfd
);
881 Container_create(Container
*self
, PyObject
*args
, PyObject
*kwds
)
883 char* template_name
= NULL
;
885 char** create_args
= {NULL
};
886 PyObject
*retval
= NULL
;
887 PyObject
*vargs
= NULL
;
888 char *bdevtype
= NULL
;
890 static char *kwlist
[] = {"template", "flags", "bdevtype", "args", NULL
};
891 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|sisO", kwlist
,
892 &template_name
, &flags
, &bdevtype
, &vargs
))
896 if (PyTuple_Check(vargs
)) {
897 create_args
= convert_tuple_to_char_pointer_array(vargs
);
903 PyErr_SetString(PyExc_ValueError
, "args needs to be a tuple");
908 if (self
->container
->create(self
->container
, template_name
, bdevtype
, NULL
,
915 /* We cannot have gotten here unless vargs was given and create_args
916 * was successfully allocated.
918 for (i
= 0; i
< PyTuple_GET_SIZE(vargs
); i
++)
919 free(create_args
[i
]);
928 Container_destroy(Container
*self
, PyObject
*args
, PyObject
*kwds
)
930 if (self
->container
->destroy(self
->container
)) {
938 Container_freeze(Container
*self
, PyObject
*args
, PyObject
*kwds
)
940 if (self
->container
->freeze(self
->container
)) {
948 Container_get_cgroup_item(Container
*self
, PyObject
*args
, PyObject
*kwds
)
950 static char *kwlist
[] = {"key", NULL
};
954 PyObject
*ret
= NULL
;
956 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s", kwlist
,
960 len
= self
->container
->get_cgroup_item(self
->container
, key
, NULL
, 0);
963 PyErr_SetString(PyExc_KeyError
, "Invalid cgroup entry");
967 value
= (char*) malloc(sizeof(char)*len
+ 1);
969 return PyErr_NoMemory();
971 if (self
->container
->get_cgroup_item(self
->container
,
972 key
, value
, len
+ 1) != len
) {
973 PyErr_SetString(PyExc_ValueError
, "Unable to read config value");
978 ret
= PyUnicode_FromString(value
);
984 Container_get_config_item(Container
*self
, PyObject
*args
, PyObject
*kwds
)
986 static char *kwlist
[] = {"key", NULL
};
990 PyObject
*ret
= NULL
;
992 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|", kwlist
,
996 len
= self
->container
->get_config_item(self
->container
, key
, NULL
, 0);
999 PyErr_SetString(PyExc_KeyError
, "Invalid configuration key");
1004 return PyUnicode_FromString("");
1007 value
= (char*) malloc(sizeof(char)*len
+ 1);
1009 return PyErr_NoMemory();
1011 if (self
->container
->get_config_item(self
->container
,
1012 key
, value
, len
+ 1) != len
) {
1013 PyErr_SetString(PyExc_ValueError
, "Unable to read config value");
1018 ret
= PyUnicode_FromString(value
);
1024 Container_get_config_path(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1026 return PyUnicode_FromString(
1027 self
->container
->get_config_path(self
->container
));
1031 Container_get_keys(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1033 static char *kwlist
[] = {"key", NULL
};
1037 PyObject
*ret
= NULL
;
1039 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|s", kwlist
,
1043 len
= self
->container
->get_keys(self
->container
, key
, NULL
, 0);
1046 PyErr_SetString(PyExc_KeyError
, "Invalid configuration key");
1050 value
= (char*) malloc(sizeof(char)*len
+ 1);
1052 return PyErr_NoMemory();
1054 if (self
->container
->get_keys(self
->container
,
1055 key
, value
, len
+ 1) != len
) {
1056 PyErr_SetString(PyExc_ValueError
, "Unable to read config keys");
1061 ret
= PyUnicode_FromString(value
);
1067 Container_get_interfaces(Container
*self
)
1070 char** interfaces
= NULL
;
1074 /* Get the interfaces */
1075 interfaces
= self
->container
->get_interfaces(self
->container
);
1077 return PyTuple_New(0);
1079 /* Count the entries */
1080 while (interfaces
[i
])
1083 /* Create the new tuple */
1084 ret
= PyTuple_New(i
);
1088 /* Add the entries to the tuple and free the memory */
1090 while (interfaces
[i
]) {
1091 PyObject
*unicode
= PyUnicode_FromString(interfaces
[i
]);
1097 PyTuple_SET_ITEM(ret
, i
, unicode
);
1101 /* Free the list of IPs */
1103 while (interfaces
[i
]) {
1104 free(interfaces
[i
]);
1113 Container_get_ips(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1115 static char *kwlist
[] = {"interface", "family", "scope", NULL
};
1116 char* interface
= NULL
;
1117 char* family
= NULL
;
1125 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|ssi", kwlist
,
1126 &interface
, &family
, &scope
))
1130 ips
= self
->container
->get_ips(self
->container
, interface
, family
, scope
);
1132 return PyTuple_New(0);
1134 /* Count the entries */
1138 /* Create the new tuple */
1139 ret
= PyTuple_New(i
);
1143 /* Add the entries to the tuple and free the memory */
1146 PyObject
*unicode
= PyUnicode_FromString(ips
[i
]);
1152 PyTuple_SET_ITEM(ret
, i
, unicode
);
1156 /* Free the list of IPs */
1168 Container_get_running_config_item(Container
*self
, PyObject
*args
,
1171 static char *kwlist
[] = {"key", NULL
};
1174 PyObject
*ret
= NULL
;
1176 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|", kwlist
,
1180 value
= self
->container
->get_running_config_item(self
->container
, key
);
1185 ret
= PyUnicode_FromString(value
);
1192 Container_load_config(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1194 static char *kwlist
[] = {"path", NULL
};
1195 PyObject
*fs_path
= NULL
;
1198 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|O&", kwlist
,
1199 PyUnicode_FSConverter
, &fs_path
))
1202 if (fs_path
!= NULL
) {
1203 path
= PyBytes_AS_STRING(fs_path
);
1204 assert(path
!= NULL
);
1207 if (self
->container
->load_config(self
->container
, path
)) {
1208 Py_XDECREF(fs_path
);
1212 Py_XDECREF(fs_path
);
1217 Container_reboot(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1219 if (self
->container
->reboot(self
->container
)) {
1227 Container_rename(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1229 char *new_name
= NULL
;
1230 static char *kwlist
[] = {"new_name", NULL
};
1232 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|", kwlist
,
1236 if (self
->container
->rename(self
->container
, new_name
)) {
1244 Container_remove_device_node(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1246 static char *kwlist
[] = {"src_path", "dest_path", NULL
};
1247 char *src_path
= NULL
;
1248 char *dst_path
= NULL
;
1249 PyObject
*py_src_path
= NULL
;
1250 PyObject
*py_dst_path
= NULL
;
1252 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "O&|O&", kwlist
,
1253 PyUnicode_FSConverter
, &py_src_path
,
1254 PyUnicode_FSConverter
, &py_dst_path
))
1257 if (py_src_path
!= NULL
) {
1258 src_path
= PyBytes_AS_STRING(py_src_path
);
1259 assert(src_path
!= NULL
);
1262 if (py_dst_path
!= NULL
) {
1263 dst_path
= PyBytes_AS_STRING(py_dst_path
);
1264 assert(dst_path
!= NULL
);
1267 if (self
->container
->remove_device_node(self
->container
, src_path
,
1269 Py_XDECREF(py_src_path
);
1270 Py_XDECREF(py_dst_path
);
1274 Py_XDECREF(py_src_path
);
1275 Py_XDECREF(py_dst_path
);
1280 Container_save_config(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1282 static char *kwlist
[] = {"path", NULL
};
1283 PyObject
*fs_path
= NULL
;
1286 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|O&", kwlist
,
1287 PyUnicode_FSConverter
, &fs_path
))
1290 if (fs_path
!= NULL
) {
1291 path
= PyBytes_AS_STRING(fs_path
);
1292 assert(path
!= NULL
);
1295 if (self
->container
->save_config(self
->container
, path
)) {
1296 Py_XDECREF(fs_path
);
1300 Py_XDECREF(fs_path
);
1305 Container_set_cgroup_item(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1307 static char *kwlist
[] = {"key", "value", NULL
};
1311 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "ss", kwlist
,
1315 if (self
->container
->set_cgroup_item(self
->container
, key
, value
)) {
1323 Container_set_config_item(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1325 static char *kwlist
[] = {"key", "value", NULL
};
1329 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "ss", kwlist
,
1333 if (self
->container
->set_config_item(self
->container
, key
, value
)) {
1341 Container_set_config_path(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1343 static char *kwlist
[] = {"path", NULL
};
1346 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s", kwlist
,
1350 if (self
->container
->set_config_path(self
->container
, path
)) {
1358 Container_shutdown(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1360 static char *kwlist
[] = {"timeout", NULL
};
1363 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|i", kwlist
,
1367 if (self
->container
->shutdown(self
->container
, timeout
)) {
1375 Container_snapshot(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1377 char *comment_path
= NULL
;
1378 static char *kwlist
[] = {"comment_path", NULL
};
1382 PyObject
*py_comment_path
= NULL
;
1384 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|O&", kwlist
,
1385 PyUnicode_FSConverter
, &py_comment_path
))
1388 if (py_comment_path
!= NULL
) {
1389 comment_path
= PyBytes_AS_STRING(py_comment_path
);
1390 assert(comment_path
!= NULL
);
1393 retval
= self
->container
->snapshot(self
->container
, comment_path
);
1395 Py_XDECREF(py_comment_path
);
1401 ret
= snprintf(newname
, 20, "snap%d", retval
);
1402 if (ret
< 0 || ret
>= 20)
1406 return PyUnicode_FromString(newname
);
1410 Container_snapshot_destroy(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1413 static char *kwlist
[] = {"name", NULL
};
1415 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|", kwlist
,
1419 if (self
->container
->snapshot_destroy(self
->container
, name
)) {
1427 Container_snapshot_list(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1429 struct lxc_snapshot
*snap
;
1431 PyObject
*list
= NULL
;
1434 snap_count
= self
->container
->snapshot_list(self
->container
, &snap
);
1436 if (snap_count
< 0) {
1437 PyErr_SetString(PyExc_KeyError
, "Unable to list snapshots");
1441 list
= PyTuple_New(snap_count
);
1442 for (i
= 0; i
< snap_count
; i
++) {
1443 PyObject
*list_entry
= NULL
;
1445 list_entry
= PyTuple_New(4);
1446 PyTuple_SET_ITEM(list_entry
, 0,
1447 PyUnicode_FromString(snap
[i
].name
));
1448 PyTuple_SET_ITEM(list_entry
, 1,
1449 PyUnicode_FromString(snap
[i
].comment_pathname
));
1450 PyTuple_SET_ITEM(list_entry
, 2,
1451 PyUnicode_FromString(snap
[i
].timestamp
));
1452 PyTuple_SET_ITEM(list_entry
, 3,
1453 PyUnicode_FromString(snap
[i
].lxcpath
));
1455 snap
[i
].free(&snap
[i
]);
1457 PyTuple_SET_ITEM(list
, i
, list_entry
);
1465 Container_snapshot_restore(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1468 char *newname
= NULL
;
1469 static char *kwlist
[] = {"name", "newname", NULL
};
1471 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|s", kwlist
,
1475 if (self
->container
->snapshot_restore(self
->container
, name
, newname
)) {
1483 Container_start(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1485 PyObject
*useinit
= NULL
;
1486 PyObject
*daemonize
= NULL
;
1487 PyObject
*close_fds
= NULL
;
1489 PyObject
*vargs
= NULL
;
1490 char** init_args
= {NULL
};
1492 PyObject
*retval
= NULL
;
1493 int init_useinit
= 0, i
= 0;
1494 static char *kwlist
[] = {"useinit", "daemonize", "close_fds",
1497 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "|OOOO", kwlist
,
1498 &useinit
, &daemonize
, &close_fds
,
1502 if (useinit
&& useinit
== Py_True
) {
1506 if (vargs
&& PyTuple_Check(vargs
)) {
1507 init_args
= convert_tuple_to_char_pointer_array(vargs
);
1513 if (close_fds
&& close_fds
== Py_True
) {
1514 self
->container
->want_close_all_fds(self
->container
, true);
1517 self
->container
->want_close_all_fds(self
->container
, false);
1520 if (!daemonize
|| daemonize
== Py_True
) {
1521 self
->container
->want_daemonize(self
->container
, true);
1524 self
->container
->want_daemonize(self
->container
, false);
1527 if (self
->container
->start(self
->container
, init_useinit
, init_args
))
1533 /* We cannot have gotten here unless vargs was given and create_args
1534 * was successfully allocated.
1536 for (i
= 0; i
< PyTuple_GET_SIZE(vargs
); i
++)
1546 Container_stop(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1548 if (self
->container
->stop(self
->container
)) {
1556 Container_unfreeze(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1558 if (self
->container
->unfreeze(self
->container
)) {
1566 Container_wait(Container
*self
, PyObject
*args
, PyObject
*kwds
)
1568 static char *kwlist
[] = {"state", "timeout", NULL
};
1572 if (! PyArg_ParseTupleAndKeywords(args
, kwds
, "s|i", kwlist
,
1576 if (self
->container
->wait(self
->container
, state
, timeout
)) {
1583 /* Function/Properties list */
1584 static PyGetSetDef Container_getseters
[] = {
1585 {"config_file_name",
1586 (getter
)Container_config_file_name
, NULL
,
1587 "Path to the container configuration",
1590 (getter
)Container_controllable
, NULL
,
1591 "Boolean indicating whether the container may be controlled",
1594 (getter
)Container_defined
, NULL
,
1595 "Boolean indicating whether the container configuration exists",
1598 (getter
)Container_init_pid
, NULL
,
1599 "PID of the container's init process in the host's PID namespace",
1602 (getter
)Container_name
, NULL
,
1606 (getter
)Container_running
, NULL
,
1607 "Boolean indicating whether the container is running or not",
1610 (getter
)Container_state
, NULL
,
1613 {NULL
, NULL
, NULL
, NULL
, NULL
}
1616 static PyMethodDef Container_methods
[] = {
1617 {"attach_interface", (PyCFunction
)Container_attach_interface
,
1618 METH_VARARGS
|METH_KEYWORDS
,
1619 "attach_interface(src_ifname, dest_ifname) -> boolean\n"
1621 "Pass a new network device to the container."
1623 {"detach_interface", (PyCFunction
)Container_detach_interface
,
1624 METH_VARARGS
|METH_KEYWORDS
,
1625 "detach_interface(ifname) -> boolean\n"
1627 "detach a network device from the container."
1629 {"add_device_node", (PyCFunction
)Container_add_device_node
,
1630 METH_VARARGS
|METH_KEYWORDS
,
1631 "add_device_node(src_path, dest_path) -> boolean\n"
1633 "Pass a new device to the container."
1635 {"attach", (PyCFunction
)Container_attach
,
1636 METH_VARARGS
|METH_KEYWORDS
,
1637 "attach(run, payload) -> int\n"
1639 "Attach to the container. Returns the pid of the attached process."
1641 {"attach_wait", (PyCFunction
)Container_attach_wait
,
1642 METH_VARARGS
|METH_KEYWORDS
,
1643 "attach(run, payload) -> int\n"
1645 "Attach to the container. Returns the exit code of the process."
1647 {"clear_config", (PyCFunction
)Container_clear_config
,
1651 "Clear any container configuration."
1653 {"clear_config_item", (PyCFunction
)Container_clear_config_item
,
1654 METH_VARARGS
|METH_KEYWORDS
,
1655 "clear_config_item(key) -> boolean\n"
1657 "Clear the current value of a config key."
1659 {"console", (PyCFunction
)Container_console
,
1660 METH_VARARGS
|METH_KEYWORDS
,
1661 "console(ttynum = -1, stdinfd = 0, stdoutfd = 1, stderrfd = 2, "
1662 "escape = 0) -> boolean\n"
1664 "Attach to container's console."
1666 {"console_getfd", (PyCFunction
)Container_console_getfd
,
1667 METH_VARARGS
|METH_KEYWORDS
,
1668 "console(ttynum = -1) -> boolean\n"
1670 "Attach to container's console."
1672 {"clone", (PyCFunction
)Container_clone
,
1673 METH_VARARGS
|METH_KEYWORDS
,
1674 "clone(newname, config_path, flags, bdevtype, bdevdata, newsize, "
1675 "hookargs) -> boolean\n"
1677 "Create a new container based on the current one."
1679 {"create", (PyCFunction
)Container_create
,
1680 METH_VARARGS
|METH_KEYWORDS
,
1681 "create(template, args = (,)) -> boolean\n"
1683 "Create a new rootfs for the container, using the given template "
1684 "and passing some optional arguments to it."
1686 {"destroy", (PyCFunction
)Container_destroy
,
1688 "destroy() -> boolean\n"
1690 "Destroys the container."
1692 {"freeze", (PyCFunction
)Container_freeze
,
1694 "freeze() -> boolean\n"
1696 "Freezes the container and returns its return code."
1698 {"get_cgroup_item", (PyCFunction
)Container_get_cgroup_item
,
1699 METH_VARARGS
|METH_KEYWORDS
,
1700 "get_cgroup_item(key) -> string\n"
1702 "Get the current value of a cgroup entry."
1704 {"get_config_item", (PyCFunction
)Container_get_config_item
,
1705 METH_VARARGS
|METH_KEYWORDS
,
1706 "get_config_item(key) -> string\n"
1708 "Get the current value of a config key."
1710 {"get_config_path", (PyCFunction
)Container_get_config_path
,
1712 "get_config_path() -> string\n"
1714 "Return the LXC config path (where the containers are stored)."
1716 {"get_keys", (PyCFunction
)Container_get_keys
,
1717 METH_VARARGS
|METH_KEYWORDS
,
1718 "get_keys(key) -> string\n"
1720 "Get a list of valid sub-keys for a key."
1722 {"get_interfaces", (PyCFunction
)Container_get_interfaces
,
1724 "get_interface() -> tuple\n"
1726 "Get a tuple of interfaces for the container."
1728 {"get_ips", (PyCFunction
)Container_get_ips
,
1729 METH_VARARGS
|METH_KEYWORDS
,
1730 "get_ips(interface, family, scope) -> tuple\n"
1732 "Get a tuple of IPs for the container."
1734 {"get_running_config_item", (PyCFunction
)Container_get_running_config_item
,
1735 METH_VARARGS
|METH_KEYWORDS
,
1736 "get_running_config_item(key) -> string\n"
1738 "Get the runtime value of a config key."
1740 {"load_config", (PyCFunction
)Container_load_config
,
1741 METH_VARARGS
|METH_KEYWORDS
,
1742 "load_config(path = DEFAULT) -> boolean\n"
1744 "Read the container configuration from its default "
1745 "location or from an alternative location if provided."
1747 {"reboot", (PyCFunction
)Container_reboot
,
1749 "reboot() -> boolean\n"
1751 "Ask the container to reboot."
1753 {"rename", (PyCFunction
)Container_rename
,
1754 METH_VARARGS
|METH_KEYWORDS
,
1755 "rename(new_name) -> boolean\n"
1757 "Rename the container."
1759 {"remove_device_node", (PyCFunction
)Container_remove_device_node
,
1760 METH_VARARGS
|METH_KEYWORDS
,
1761 "remove_device_node(src_path, dest_path) -> boolean\n"
1763 "Remove a device from the container."
1765 {"save_config", (PyCFunction
)Container_save_config
,
1766 METH_VARARGS
|METH_KEYWORDS
,
1767 "save_config(path = DEFAULT) -> boolean\n"
1769 "Save the container configuration to its default "
1770 "location or to an alternative location if provided."
1772 {"set_cgroup_item", (PyCFunction
)Container_set_cgroup_item
,
1773 METH_VARARGS
|METH_KEYWORDS
,
1774 "set_cgroup_item(key, value) -> boolean\n"
1776 "Set a cgroup entry to the provided value."
1778 {"set_config_item", (PyCFunction
)Container_set_config_item
,
1779 METH_VARARGS
|METH_KEYWORDS
,
1780 "set_config_item(key, value) -> boolean\n"
1782 "Set a config key to the provided value."
1784 {"set_config_path", (PyCFunction
)Container_set_config_path
,
1785 METH_VARARGS
|METH_KEYWORDS
,
1786 "set_config_path(path) -> boolean\n"
1788 "Set the LXC config path (where the containers are stored)."
1790 {"shutdown", (PyCFunction
)Container_shutdown
,
1791 METH_VARARGS
|METH_KEYWORDS
,
1792 "shutdown(timeout = -1) -> boolean\n"
1794 "Sends SIGPWR to the container and wait for it to shutdown."
1795 "-1 means wait forever, 0 means skip waiting."
1797 {"snapshot", (PyCFunction
)Container_snapshot
,
1798 METH_VARARGS
|METH_KEYWORDS
,
1799 "snapshot(comment_path = None) -> string\n"
1801 "Snapshot the container and return the snapshot name "
1802 "(or False on error)."
1804 {"snapshot_destroy", (PyCFunction
)Container_snapshot_destroy
,
1805 METH_VARARGS
|METH_KEYWORDS
,
1806 "snapshot_destroy(name) -> boolean\n"
1808 "Destroy a snapshot."
1810 {"snapshot_list", (PyCFunction
)Container_snapshot_list
,
1812 "snapshot_list() -> tuple of snapshot tuples\n"
1814 "List all snapshots for a container."
1816 {"snapshot_restore", (PyCFunction
)Container_snapshot_restore
,
1817 METH_VARARGS
|METH_KEYWORDS
,
1818 "snapshot_restore(name, newname = None) -> boolean\n"
1820 "Restore a container snapshot. If newname is provided a new "
1821 "container will be created from the snapshot, otherwise an in-place "
1822 "restore will be attempted."
1824 {"start", (PyCFunction
)Container_start
,
1825 METH_VARARGS
|METH_KEYWORDS
,
1826 "start(useinit = False, daemonize=True, close_fds=False, "
1827 "cmd = (,)) -> boolean\n"
1829 "Start the container, return True on success.\n"
1830 "When set useinit will make LXC use lxc-init to start the container.\n"
1831 "The container can be started in the foreground with daemonize=False.\n"
1832 "All fds may also be closed by passing close_fds=True."
1834 {"stop", (PyCFunction
)Container_stop
,
1836 "stop() -> boolean\n"
1838 "Stop the container and returns its return code."
1840 {"unfreeze", (PyCFunction
)Container_unfreeze
,
1842 "unfreeze() -> boolean\n"
1844 "Unfreezes the container and returns its return code."
1846 {"wait", (PyCFunction
)Container_wait
,
1847 METH_VARARGS
|METH_KEYWORDS
,
1848 "wait(state, timeout = -1) -> boolean\n"
1850 "Wait for the container to reach a given state or timeout."
1852 {NULL
, NULL
, 0, NULL
}
1855 static PyTypeObject _lxc_ContainerType
= {
1856 PyVarObject_HEAD_INIT(NULL
, 0)
1857 "lxc.Container", /* tp_name */
1858 sizeof(Container
), /* tp_basicsize */
1859 0, /* tp_itemsize */
1860 (destructor
)Container_dealloc
, /* tp_dealloc */
1864 0, /* tp_reserved */
1866 0, /* tp_as_number */
1867 0, /* tp_as_sequence */
1868 0, /* tp_as_mapping */
1872 0, /* tp_getattro */
1873 0, /* tp_setattro */
1874 0, /* tp_as_buffer */
1875 Py_TPFLAGS_DEFAULT
|
1876 Py_TPFLAGS_BASETYPE
, /* tp_flags */
1877 "Container objects", /* tp_doc */
1878 0, /* tp_traverse */
1880 0, /* tp_richcompare */
1881 0, /* tp_weaklistoffset */
1883 0, /* tp_iternext */
1884 Container_methods
, /* tp_methods */
1886 Container_getseters
, /* tp_getset */
1889 0, /* tp_descr_get */
1890 0, /* tp_descr_set */
1891 0, /* tp_dictoffset */
1892 (initproc
)Container_init
, /* tp_init */
1894 Container_new
, /* tp_new */
1897 static PyMethodDef LXC_methods
[] = {
1898 {"arch_to_personality", (PyCFunction
)LXC_arch_to_personality
, METH_O
,
1899 "Returns the process personality of the corresponding architecture"},
1900 {"attach_run_command", (PyCFunction
)LXC_attach_run_command
, METH_O
,
1901 "Runs a command when attaching, to use as the run parameter for attach "
1903 {"attach_run_shell", (PyCFunction
)LXC_attach_run_shell
, METH_O
,
1904 "Starts up a shell when attaching, to use as the run parameter for "
1905 "attach or attach_wait"},
1906 {"get_global_config_item", (PyCFunction
)LXC_get_global_config_item
,
1907 METH_VARARGS
|METH_KEYWORDS
,
1908 "Returns the current LXC config path"},
1909 {"get_version", (PyCFunction
)LXC_get_version
, METH_NOARGS
,
1910 "Returns the current LXC library version"},
1911 {"list_containers", (PyCFunction
)LXC_list_containers
,
1912 METH_VARARGS
|METH_KEYWORDS
,
1913 "Returns a list of container names or objects"},
1914 {NULL
, NULL
, 0, NULL
}
1917 static PyModuleDef _lxcmodule
= {
1918 PyModuleDef_HEAD_INIT
,
1920 "Binding for liblxc in python",
1931 if (PyType_Ready(&_lxc_ContainerType
) < 0)
1934 m
= PyModule_Create(&_lxcmodule
);
1938 Py_INCREF(&_lxc_ContainerType
);
1939 PyModule_AddObject(m
, "Container", (PyObject
*)&_lxc_ContainerType
);
1942 d
= PyModule_GetDict(m
);
1944 #define PYLXC_EXPORT_CONST(c) \
1945 PyDict_SetItemString(d, #c, PyLong_FromLong(c))
1947 /* namespace flags (no other python lib exports this) */
1948 PYLXC_EXPORT_CONST(CLONE_NEWUTS
);
1949 PYLXC_EXPORT_CONST(CLONE_NEWIPC
);
1950 PYLXC_EXPORT_CONST(CLONE_NEWUSER
);
1951 PYLXC_EXPORT_CONST(CLONE_NEWPID
);
1952 PYLXC_EXPORT_CONST(CLONE_NEWNET
);
1953 PYLXC_EXPORT_CONST(CLONE_NEWNS
);
1955 /* attach: environment variable handling */
1956 PYLXC_EXPORT_CONST(LXC_ATTACH_CLEAR_ENV
);
1957 PYLXC_EXPORT_CONST(LXC_ATTACH_KEEP_ENV
);
1959 /* attach: attach options */
1960 PYLXC_EXPORT_CONST(LXC_ATTACH_DEFAULT
);
1961 PYLXC_EXPORT_CONST(LXC_ATTACH_DROP_CAPABILITIES
);
1962 PYLXC_EXPORT_CONST(LXC_ATTACH_LSM_EXEC
);
1963 PYLXC_EXPORT_CONST(LXC_ATTACH_LSM_NOW
);
1964 PYLXC_EXPORT_CONST(LXC_ATTACH_MOVE_TO_CGROUP
);
1965 PYLXC_EXPORT_CONST(LXC_ATTACH_REMOUNT_PROC_SYS
);
1966 PYLXC_EXPORT_CONST(LXC_ATTACH_SET_PERSONALITY
);
1968 /* clone: clone flags */
1969 PYLXC_EXPORT_CONST(LXC_CLONE_KEEPBDEVTYPE
);
1970 PYLXC_EXPORT_CONST(LXC_CLONE_KEEPMACADDR
);
1971 PYLXC_EXPORT_CONST(LXC_CLONE_KEEPNAME
);
1972 PYLXC_EXPORT_CONST(LXC_CLONE_MAYBE_SNAPSHOT
);
1973 PYLXC_EXPORT_CONST(LXC_CLONE_SNAPSHOT
);
1975 /* create: create flags */
1976 PYLXC_EXPORT_CONST(LXC_CREATE_QUIET
);
1978 #undef PYLXC_EXPORT_CONST
1984 * kate: space-indent on; indent-width 4; mixedindent off; indent-mode cstyle;