-INCLUDES= -I$(top_srcdir)/src -DLXCPATH="\"$(localstatedir)/lxc\""
+INCLUDES= -I$(top_srcdir)/src -DLXCPATH="\"$(localstatedir)/lxc\"" -DLXCBINDIR="\"$(bindir)\""
lib_LTLIBRARIES = liblxc.la
pkginclude_HEADERS = \
monitor.h \
destroy.c \
start.c \
stop.c \
- execute.c \
monitor.c monitor.h \
kill.c \
freezer.c \
lxc-checkconfig
bin_PROGRAMS = \
+ lxc-init \
lxc-create \
lxc-destroy \
lxc-stop \
lxc-restart \
lxc-version
+lxc_init_SOURCES = lxc_init.c
+lxc_init_LDADD = liblxc.la
+
lxc_create_SOURCES = lxc_create.c lxc_config.c lxc_config.h
lxc_create_LDADD = liblxc.la
+++ /dev/null
-/*
- * lxc: linux Container library
- *
- * (C) Copyright IBM Corp. 2007, 2008
- *
- * Authors:
- * Daniel Lezcano <dlezcano at fr.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#define _GNU_SOURCE
-#include <stdio.h>
-#undef _GNU_SOURCE
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <sys/file.h>
-#include <sys/mount.h>
-
-#include <lxc/lxc.h>
-
-LXC_TTY_HANDLER(SIGINT);
-LXC_TTY_HANDLER(SIGQUIT);
-
-int lxc_execute(const char *name, int argc, char *argv[],
- lxc_callback_t preexec, void *data)
-{
- char init[MAXPATHLEN];
- char *val = NULL, *vinit = "[vinit]";
- int fd, lock, sv[2], sync = 0, err = -1;
- pid_t pid;
- int clone_flags;
-
- lock = lxc_get_lock(name);
- if (!lock) {
- lxc_log_error("'%s' is busy", name);
- return -1;
- }
-
- if (lock < 0) {
- lxc_log_error("failed to acquire lock on '%s':%s",
- name, strerror(-lock));
- return -1;
- }
-
- if (lxc_setstate(name, STARTING)) {
- lxc_log_error("failed to set state %s", lxc_state2str(STARTING));
- goto out;
- }
-
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
- lxc_log_syserror("failed to create communication socketpair");
- goto err;
- }
-
- LXC_TTY_ADD_HANDLER(SIGINT);
- LXC_TTY_ADD_HANDLER(SIGQUIT);
-
- clone_flags = CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
- if (conf_has_utsname(name))
- clone_flags |= CLONE_NEWUTS;
- if (conf_has_network(name))
- clone_flags |= CLONE_NEWNET;
-
- pid = fork_ns(clone_flags);
- if (pid < 0) {
- lxc_log_syserror("failed to fork into a new namespace");
- goto err_fork_ns;
- }
-
- if (!pid) {
-
- pid = fork();
- if (pid < 0) {
- lxc_log_syserror("failed to fork");
- return 1;
- }
-
- if (!pid) {
- close(sv[1]);
- fcntl(sv[0], F_SETFD, FD_CLOEXEC);
-
- if (write(sv[0], &sync, sizeof(sync)) < 0) {
- lxc_log_syserror("failed to write socket");
- exit(1);
- }
-
- if (read(sv[0], &sync, sizeof(sync)) < 0) {
- lxc_log_syserror("failed to read socket");
- exit(1);
- }
-
- if (lxc_setup(name)) {
- lxc_log_error("failed to setup the container");
- goto error;
- }
-
- if (mount("proc", "/proc", "proc", 0, NULL)) {
- lxc_log_syserror("failed to mount '/proc'");
- goto error;
- }
-
- if (clone_flags & CLONE_NEWNET)
- if (mount("sysfs", "/sys", "sysfs", 0, NULL)) {
- lxc_log_syserror("failed to mount '/sys'");
- /* continue: non fatal error until sysfs not per
- namespace */
- }
-
- if (preexec)
- if (preexec(name, argc, argv, data)) {
- lxc_log_error("preexec callback has failed");
- return -1;
- }
-
- execvp(argv[0], argv);
- lxc_log_syserror("failed to exec %s", argv[0]);
- error:
- if (write(sv[0], &sync, sizeof(sync)) < 0)
- lxc_log_syserror("failed to write the socket");
-
- exit(1);
- }
-
- setsid();
- close(0);
- close(1);
- close(2);
-
- if (prctl(PR_SET_NAME, vinit, 0, 0, 0))
- lxc_log_syserror("failed to set process name");
-
- close(sv[0]);
- close(sv[1]);
-
- for (;;) {
- int status;
- if (wait(&status) < 0) {
- if (errno == ECHILD)
- exit(0);
- if (errno == EINTR)
- continue;
- lxc_log_syserror("failed to wait child");
- exit(1);
- }
- }
- }
-
- close(sv[0]);
-
- if (read(sv[1], &sync, sizeof(sync)) < 0) {
- lxc_log_syserror("failed to read the socket");
- goto err_pipe_read;
- }
-
- if (lxc_link_nsgroup(name, pid))
- lxc_log_warning("cgroupfs not found: cgroup disabled");
-
- if (clone_flags & CLONE_NEWNET && conf_create_network(name, pid)) {
- lxc_log_error("failed to create the configured network");
- goto err_create_network;
- }
-
- if (write(sv[1], &sync, sizeof(sync)) < 0) {
- lxc_log_syserror("failed to write the socket");
- goto err_pipe_write;
- }
-
- err = read(sv[1], &sync, sizeof(sync));
- if (err < 0) {
- lxc_log_error("failed to read the socket");
- goto err_pipe_read2;
- }
-
- if (err > 0) {
- lxc_log_error("something went wrong with %d", pid);
- /* TODO : check status etc ... */
- waitpid(pid, NULL, 0);
- goto err_child_failed;
- }
-
- snprintf(init, MAXPATHLEN, LXCPATH "/%s/init", name);
-
- fd = open(init, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
- if (fd < 0) {
- lxc_log_syserror("failed to open %s", init);
- goto err_open;
- }
-
- if (!asprintf(&val, "%d", pid)) {
- lxc_log_syserror("failed to allocate memory");
- goto err_open;
- }
-
- if (write(fd, val, strlen(val)) < 0) {
- lxc_log_syserror("failed to write init pid");
- goto err_write;
- }
-
- if (lxc_setstate(name, RUNNING)) {
- lxc_log_error("failed to set state to %s", lxc_state2str(RUNNING));
- goto err_state_failed;
- }
-
-wait_again:
- if (waitpid(pid, NULL, 0) < 0) {
- if (errno == EINTR)
- goto wait_again;
- lxc_log_syserror("failed to wait the pid %d", pid);
- goto err_waitpid_failed;
- }
-
- if (lxc_setstate(name, STOPPING))
- lxc_log_error("failed to set state %s", lxc_state2str(STOPPING));
-
- if (clone_flags & CLONE_NEWNET && conf_destroy_network(name))
- lxc_log_error("failed to destroy the network");
-
- err = 0;
-out:
- if (lxc_setstate(name, STOPPED))
- lxc_log_error("failed to set state %s", lxc_state2str(STOPPED));
-
- lxc_unlink_nsgroup(name);
- unlink(init);
- free(val);
- lxc_put_lock(lock);
-
- return err;
-
-err_write:
- close(fd);
-
-err_state_failed:
-err_child_failed:
-err_pipe_read2:
-err_pipe_write:
- if (clone_flags & CLONE_NEWNET)
- conf_destroy_network(name);
-err_create_network:
-err_pipe_read:
-err_open:
-err_waitpid_failed:
- if (lxc_setstate(name, ABORTING))
- lxc_log_error("failed to set state %s", lxc_state2str(STOPPED));
-
- kill(pid, SIGKILL);
-err_fork_ns:
- LXC_TTY_DEL_HANDLER(SIGQUIT);
- LXC_TTY_DEL_HANDLER(SIGINT);
- close(sv[0]);
- close(sv[1]);
-err:
- goto out;
-}
struct lxc_mem_stat;
-typedef int (*lxc_callback_t)(const char *name, int argc,
- char *argv[], void *data);
-
/*
* Create the container object. Creates the /lxc/<name> directory
* and fills it with the files corresponding to the configuration
/*
* Start the container previously created with lxc_create.
* @name : the name of the container
- * @argc : the number of arguments of the command line
* @argv : an array of char * corresponding to the commande line
- * @prestart : hooks will be called just before the command execs
* Returns 0 on sucess, < 0 otherwise
*/
-extern int lxc_start(const char *name, int argc, char *argv[],
- lxc_callback_t prestart, void *data);
-
-/*
- * Create the container and start it directly, using the argc, argv
- * parameter. This command is for application container.
- * At the end of the exec'ed command, the container will
- * automatically autodestroy.
- * @name : the name of the container
- * @conf : the configuration data
- * @argc : the number of arguments of the command line
- * @argv : an array of char * corresponding to the commande line
- * @preexec : hooks will be called just before the command execs
- * Returns 0 on success, < 0 otherwise
- */
-extern int lxc_execute(const char *name, int argc, char *argv[],
- lxc_callback_t preexec, void *data);
+extern int lxc_start(const char *name, char *argv[]);
/*
* Stop the container previously started with lxc_start or lxc_exec
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <libgen.h>
{
char opt;
char *name = NULL, *file = NULL;
- char **args;
+ static char **args;
char path[MAXPATHLEN];
int nbargs = 0;
int autodestroy = 0;
if (!name || !argv[optind] || !strlen(argv[optind]))
usage(argv[0]);
- args = &argv[optind];
argc -= nbargs;
if (lxc_config_init(&lxc_conf)) {
goto out;
}
- if (file) {
-
- if (lxc_config_read(file, &lxc_conf)) {
- fprintf(stderr, "invalid configuration file\n");
- goto out;
- }
-
+ if (file && lxc_config_read(file, &lxc_conf)) {
+ fprintf(stderr, "invalid configuration file\n");
+ goto out;
}
snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
autodestroy = 1;
}
- if (lxc_execute(name, argc, args, NULL, NULL)) {
+ /* lxc-init --mount-procfs -- .... */
+ args = malloc((argc + 3)*sizeof(*args));
+ if (!args) {
+ fprintf(stderr, "failed to allocate memory for '%s'\n", name);
+ goto out;
+ }
+
+ nbargs = 0;
+ args[nbargs++] = LXCBINDIR "/lxc-init";
+ args[nbargs++] = "--mount-procfs";
+ args[nbargs++] = "--";
+
+ for (opt = 0; opt < argc; opt++)
+ args[nbargs++] = argv[optind++];
+
+ if (lxc_start(name, args)) {
fprintf(stderr, "failed to execute '%s'\n", name);
goto out;
}
ret = 0;
-
out:
if (autodestroy) {
if (lxc_destroy(name)) {
--- /dev/null
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/mount.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
+static int mount_sysfs;
+static int mount_procfs;
+
+static struct option options[] = {
+ { "mount-sysfs", no_argument, &mount_sysfs, 1 },
+ { "mount-procfs", no_argument, &mount_procfs, 1 },
+};
+
+int main(int argc, char *argv[])
+{
+ pid_t pid;
+
+ int nbargs = 0;
+ char **aargv;
+
+ while (1) {
+ int ret = getopt_long_only(argc, argv, "", options, NULL);
+ if (ret == -1)
+ break;
+ if (ret == '?')
+ exit(1);
+ nbargs++;
+ }
+
+ if (!argv[optind]) {
+ fprintf(stderr, "missing command to launch\n");
+ exit(1);
+ }
+
+ aargv = &argv[optind];
+ argc -= nbargs;
+
+ pid = fork();
+
+ if (pid < 0)
+ exit(1);
+
+ if (!pid) {
+
+ if (mount_sysfs && mount("sysfs", "/sys", "sysfs", 0, NULL)) {
+ fprintf(stderr, "failed to mount '/sys'\n");
+ exit(1);
+ }
+
+ if (mount_procfs && mount("proc", "/proc", "proc", 0, NULL)) {
+ fprintf(stderr, "failed to mount '/proc'\n");
+ exit(1);
+ }
+
+ execvp(aargv[0], aargv);
+ fprintf(stderr, "failed to exec: %s\n", aargv[0]);
+ exit(1);
+ }
+
+ for (;;) {
+ int status;
+ if (wait(&status) < 0) {
+ if (errno == ECHILD)
+ exit(0);
+ if (errno == EINTR)
+ continue;
+ fprintf(stderr, "failed to wait child\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
args = &argv[optind];
argc -= nbargs;
- if (lxc_start(name, argc, args, NULL, NULL)) {
+ if (lxc_start(name, args)) {
fprintf(stderr, "failed to start %s\n", name);
return 1;
}
LXC_TTY_HANDLER(SIGINT);
LXC_TTY_HANDLER(SIGQUIT);
-int lxc_start(const char *name, int argc, char *argv[],
- lxc_callback_t prestart, void *data)
+int lxc_start(const char *name, char *argv[])
{
char init[MAXPATHLEN];
char *val = NULL;
goto out_child;
}
- /* If a callback has been passed, call it before doing exec */
- if (prestart)
- if (prestart(name, argc, argv, data)) {
- lxc_log_error("prestart callback has failed");
- goto out_child;
- }
-
if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
lxc_log_syserror("failed to remove CAP_SYS_BOOT capability");
goto out_child;