]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/start.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <dlezcano at fr.ibm.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include <sys/param.h>
35 #include <sys/mount.h>
36 #include <sys/types.h>
37 #include <sys/prctl.h>
42 LXC_TTY_HANDLER(SIGINT
);
43 LXC_TTY_HANDLER(SIGQUIT
);
45 int opentty(const char *ttyname
)
49 fd
= open(ttyname
, O_RDWR
| O_NONBLOCK
);
51 lxc_log_syserror("open '%s'", ttyname
);
55 flags
= fcntl(fd
, F_GETFL
);
57 fcntl(fd
, F_SETFL
, flags
);
59 for (i
= 0; i
< fd
; i
++)
61 for (i
= 0; i
< 3; i
++)
70 int lxc_start(const char *name
, int argc
, char *argv
[],
71 lxc_callback_t prestart
, void *data
)
73 char init
[MAXPATHLEN
];
75 char ttyname
[MAXPATHLEN
];
76 int fd
, lock
, sv
[2], sync
= 0, err
= -1;
80 lock
= lxc_get_lock(name
);
82 lxc_log_error("'%s' is busy", name
);
87 lxc_log_error("failed to acquire lock on '%s':%s",
88 name
, strerror(-lock
));
92 /* Begin the set the state to STARTING*/
93 if (lxc_setstate(name
, STARTING
)) {
94 lxc_log_error("failed to set state %s", lxc_state2str(STARTING
));
98 if (readlink("/proc/self/fd/0", ttyname
, sizeof(ttyname
)) < 0) {
99 lxc_log_syserror("failed to read '/proc/self/fd/0'");
104 /* Synchro socketpair */
105 if (socketpair(AF_LOCAL
, SOCK_STREAM
, 0, sv
)) {
106 lxc_log_syserror("failed to create communication socketpair");
110 /* Avoid signals from terminal */
111 LXC_TTY_ADD_HANDLER(SIGINT
);
112 LXC_TTY_ADD_HANDLER(SIGQUIT
);
114 clone_flags
= CLONE_NEWPID
|CLONE_NEWIPC
|CLONE_NEWNS
;
115 if (conf_has_utsname(name
))
116 clone_flags
|= CLONE_NEWUTS
;
117 if (conf_has_network(name
))
118 clone_flags
|= CLONE_NEWNET
;
120 /* Create a process in a new set of namespaces */
121 pid
= fork_ns(clone_flags
);
123 lxc_log_syserror("failed to fork into a new namespace");
131 /* Be sure we don't inherit this after the exec */
132 fcntl(sv
[0], F_SETFD
, FD_CLOEXEC
);
134 /* Tell our father he can begin to configure the container */
135 if (write(sv
[0], &sync
, sizeof(sync
)) < 0) {
136 lxc_log_syserror("failed to write socket");
140 /* Wait for the father to finish the configuration */
141 if (read(sv
[0], &sync
, sizeof(sync
)) < 0) {
142 lxc_log_syserror("failed to read socket");
146 /* Setup the container, ip, names, utsname, ... */
147 if (lxc_setup(name
)) {
148 lxc_log_error("failed to setup the container");
149 if (write(sv
[0], &sync
, sizeof(sync
)) < 0)
150 lxc_log_syserror("failed to write the socket");
155 if (opentty(ttyname
)) {
156 lxc_log_syserror("failed to open the tty");
160 if (mount(ttyname
, "/dev/console", "none", MS_BIND
, 0)) {
161 lxc_log_syserror("failed to mount '/dev/console'");
165 /* If a callback has been passed, call it before doing exec */
167 if (prestart(name
, argc
, argv
, data
)) {
168 lxc_log_error("prestart callback has failed");
172 execvp(argv
[0], argv
);
173 lxc_log_syserror("failed to exec %s", argv
[0]);
175 /* If the exec fails, tell that to our father */
176 if (write(sv
[0], &sync
, sizeof(sync
)) < 0)
177 lxc_log_syserror("failed to write the socket");
184 /* Wait for the child to be ready */
185 if (read(sv
[1], &sync
, sizeof(sync
)) < 0) {
186 lxc_log_syserror("failed to read the socket");
190 if (lxc_link_nsgroup(name
, pid
))
191 lxc_log_warning("cgroupfs not found: cgroup disabled");
193 /* Create the network configuration */
194 if (clone_flags
& CLONE_NEWNET
&& conf_create_network(name
, pid
)) {
195 lxc_log_error("failed to create the configured network");
196 goto err_create_network
;
199 /* Tell the child to continue its initialization */
200 if (write(sv
[1], &sync
, sizeof(sync
)) < 0) {
201 lxc_log_syserror("failed to write the socket");
205 /* Wait for the child to exec or returning an error */
206 err
= read(sv
[1], &sync
, sizeof(sync
));
208 lxc_log_error("failed to read the socket");
213 lxc_log_error("something went wrong with %d", pid
);
214 /* TODO : check status etc ... */
215 waitpid(pid
, NULL
, 0);
216 goto err_child_failed
;
219 asprintf(&val
, "%d\n", pid
);
221 snprintf(init
, MAXPATHLEN
, LXCPATH
"/%s/init", name
);
223 fd
= open(init
, O_WRONLY
|O_CREAT
|O_TRUNC
, S_IRUSR
|S_IWUSR
);
225 lxc_log_syserror("failed to open '%s'", init
);
229 if (write(fd
, val
, strlen(val
)) < 0) {
230 lxc_log_syserror("failed to write the init pid");
236 if (lxc_setstate(name
, RUNNING
)) {
237 lxc_log_error("failed to set state to %s",
238 lxc_state2str(RUNNING
));
239 goto err_state_failed
;
243 if (waitpid(pid
, NULL
, 0) < 0) {
246 lxc_log_syserror("failed to wait the pid %d", pid
);
247 goto err_waitpid_failed
;
250 if (lxc_setstate(name
, STOPPING
))
251 lxc_log_error("failed to set state %s", lxc_state2str(STOPPING
));
253 if (clone_flags
& CLONE_NEWNET
&& conf_destroy_network(name
))
254 lxc_log_error("failed to destroy the network");
258 if (lxc_setstate(name
, STOPPED
))
259 lxc_log_error("failed to set state %s", lxc_state2str(STOPPED
));
261 lxc_unlink_nsgroup(name
);
275 if (clone_flags
& CLONE_NEWNET
)
276 conf_destroy_network(name
);
280 if (lxc_setstate(name
, ABORTING
))
281 lxc_log_error("failed to set state %s", lxc_state2str(STOPPED
));
285 LXC_TTY_DEL_HANDLER(SIGQUIT
);
286 LXC_TTY_DEL_HANDLER(SIGINT
);