split container operation to hyper_setup_container() and hyper_run_process()

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
This commit is contained in:
Lai Jiangshan
2016-07-06 17:15:42 +08:00
parent 98b8211ddc
commit 54aed5efc5
3 changed files with 19 additions and 192 deletions
+9 -60
View File
@@ -499,47 +499,21 @@ static int hyper_rescan_scsi(void)
struct hyper_container_arg {
struct hyper_container *c;
struct hyper_pod *pod;
int ipcns;
int utsns;
int pipe[2];
};
static int hyper_container_init(void *data)
static int hyper_setup_container_rootfs(void *data)
{
struct hyper_container_arg *arg = data;
struct hyper_container *container = arg->c;
char root[512], rootfs[512];
int setup_dns;
fprintf(stdout, "%s in\n", __func__);
if (container->exec.argv == NULL) {
fprintf(stdout, "no cmd!\n");
goto fail;
}
if (setns(arg->ipcns, CLONE_NEWIPC) < 0) {
perror("setns to ipcns of pod init faild");
goto fail;
}
if (setns(arg->utsns, CLONE_NEWUTS) < 0) {
perror("setns to ipcns of pod init faild");
goto fail;
}
if (hyper_rescan_scsi() < 0) {
fprintf(stdout, "rescan scsi failed\n");
goto fail;
}
// set early env. the container env config can overwrite it
setenv("HOME", "/root", 1);
setenv("HOSTNAME", arg->pod->hostname, 1);
if (container->exec.tty)
setenv("TERM", "xterm", 1);
else
unsetenv("TERM");
if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
perror("mount SLAVE failed");
goto fail;
@@ -650,7 +624,8 @@ static int hyper_container_init(void *data)
}
hyper_send_type(arg->pipe[1], READY);
hyper_exec_process(&container->exec);
fflush(NULL);
_exit(0);
fail:
hyper_send_type(arg->pipe[1], ERROR);
@@ -674,23 +649,15 @@ static int hyper_setup_pty(struct hyper_container *c)
return -1;
}
if (hyper_setup_exec_tty(&c->exec) < 0) {
fprintf(stderr, "setup container pts failed\n");
return -1;
}
return 0;
}
int hyper_start_container(struct hyper_container *container,
int utsns, int ipcns, struct hyper_pod *pod)
int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod)
{
int stacksize = getpagesize() * 42;
struct hyper_container_arg arg = {
.c = container,
.pod = pod,
.utsns = utsns,
.ipcns = ipcns,
.pipe = {-1, -1},
};
int flags = CLONE_NEWNS | SIGCHLD;
@@ -699,24 +666,18 @@ int hyper_start_container(struct hyper_container *container,
uint32_t type;
int pid;
if (container->image == NULL || container->exec.argv == NULL) {
fprintf(stdout, "container root image %s, argv %p\n",
container->image, container->exec.argv);
goto fail;
}
if (pipe2(arg.pipe, O_CLOEXEC) < 0) {
perror("create pipe between pod init execcmd failed");
goto fail;
}
if (hyper_setup_pty(container) < 0) {
fprintf(stderr, "setup pty device for container failed\n");
if (hyper_setup_container_portmapping(container, pod) < 0) {
perror("fail to setup port mapping for container");
goto fail;
}
if (hyper_watch_exec_pty(&container->exec, pod) < 0) {
fprintf(stderr, "faile to watch container pty\n");
if (hyper_setup_pty(container) < 0) {
fprintf(stderr, "setup pty device for container failed\n");
goto fail;
}
@@ -726,7 +687,7 @@ int hyper_start_container(struct hyper_container *container,
goto fail;
}
pid = clone(hyper_container_init, stack + stacksize, flags, &arg);
pid = clone(hyper_setup_container_rootfs, stack + stacksize, flags, &arg);
free(stack);
if (pid < 0) {
perror("create child process failed");
@@ -746,24 +707,12 @@ int hyper_start_container(struct hyper_container *container,
goto fail;
}
container->exec.pid = pid;
list_add_tail(&container->exec.list, &pod->exec_head);
container->exec.ref++;
close(arg.pipe[0]);
close(arg.pipe[1]);
fprintf(stdout, "container %s,init pid %d,ref %d\n", container->id, pid, container->exec.ref);
return 0;
fail:
close(container->ns);
hyper_reset_event(&container->exec.stdinev);
hyper_reset_event(&container->exec.stdoutev);
hyper_reset_event(&container->exec.stderrev);
container->ns = -1;
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
container->exec.code = -1;
container->exec.seq = 0;
container->exec.ref = 0;
close(arg.pipe[0]);
close(arg.pipe[1]);
return -1;
+1 -2
View File
@@ -53,8 +53,7 @@ struct hyper_container {
struct hyper_pod;
int hyper_start_container(struct hyper_container *container,
int utsns, int ipcns, struct hyper_pod *pod);
int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod);
struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id);
void hyper_cleanup_container(struct hyper_container *container, struct hyper_pod *pod);
void hyper_cleanup_containers(struct hyper_pod *pod);
+9 -130
View File
@@ -274,141 +274,18 @@ fail:
goto out;
}
struct hyper_stage0_arg {
struct hyper_pod *pod;
struct hyper_container *container;
int ctl_pipe[2];
};
// stage0: enter the pidns
static int hyper_container_stage0(void *data)
{
int pidns, ipcns, utsns, ret;
struct hyper_container *c;
struct hyper_stage0_arg *arg;
struct hyper_pod *pod;
char path[64];
arg = data;
pod = arg->pod;
c = arg->container;
ret = pidns = ipcns = utsns = -1;
sprintf(path, "/proc/%d/ns/pid", pod->init_pid);
pidns = open(path, O_RDONLY| O_CLOEXEC);
if (pidns < 0) {
perror("fail to open pidns of pod init");
goto out;
}
/* enter pidns of pod init, so the children of this process will run in
* pidns of pod init, see man 2 setns */
if (setns(pidns, CLONE_NEWPID) < 0) {
perror("enter pidns of pod init failed");
goto out;
}
sprintf(path, "/proc/%d/ns/uts", pod->init_pid);
utsns = open(path, O_RDONLY| O_CLOEXEC);
if (utsns < 0) {
perror("fail to open utsns of pod init");
goto out;
}
sprintf(path, "/proc/%d/ns/ipc", pod->init_pid);
ipcns = open(path, O_RDONLY| O_CLOEXEC);
if (ipcns < 0) {
perror("fail to open ipcns of pod init");
goto out;
}
ret = hyper_start_container(c, utsns, ipcns, pod);
out:
close(pidns);
close(utsns);
close(ipcns);
if (hyper_send_type(arg->ctl_pipe[1], ret ? ERROR : READY) < 0) {
fprintf(stderr, "container init send ready message failed\n");
}
/* hyper_container_stage0 shares fd table with init, let init closes pipe. */
//close(arg->ctl_pipe[0]);
//close(arg->ctl_pipe[1]);
_exit(ret);
}
int hyper_start_container_stage0(struct hyper_container *c, struct hyper_pod *pod)
{
int stacksize = getpagesize() * 4;
void *stack = NULL;
struct hyper_stage0_arg arg = {
.pod = pod,
.container = c,
.ctl_pipe = {-1, -1},
};
int ret = -1, pid, status;
uint32_t type;
if (pipe2(arg.ctl_pipe, O_CLOEXEC) < 0) {
perror("create pipe between hyper init and pod init failed");
goto out;
}
stack = malloc(stacksize);
if (stack == NULL) {
perror("fail to allocate stack for container init");
goto out;
}
if (hyper_setup_container_portmapping(c, pod) < 0) {
perror("fail to setup port mapping for container");
goto out;
}
pid = clone(hyper_container_stage0, stack + stacksize, CLONE_VM| CLONE_FILES| SIGQUIT, &arg);
if (pid < 0) {
perror("enter container pid ns failed");
goto out;
}
if (waitpid(pid, &status, __WCLONE) <= 0) {
perror("waiting hyper_container_stage0 finish failed");
goto out;
}
/* Wait for container start */
if (hyper_get_type(arg.ctl_pipe[0], &type) < 0) {
perror("get enter_container_pidns ready message failed");
goto out;
}
if (type != READY) {
fprintf(stderr, "get incorrect enter_container_pidns message type %d, expect READY\n",
type);
goto out;
}
/* container process is spawned and ready to execute */
pod->remains++;
ret = 0;
out:
close(arg.ctl_pipe[0]);
close(arg.ctl_pipe[1]);
free(stack);
return ret;
}
int hyper_start_containers(struct hyper_pod *pod)
{
struct hyper_container *c;
// TODO: setup containers and run container init processes
// via separated hyperstart APIs
list_for_each_entry(c, &pod->containers, list) {
if (hyper_start_container_stage0(c, pod) < 0)
if (hyper_setup_container(c, pod) < 0)
return -1;
if (hyper_run_process(&c->exec) < 0)
return -1;
pod->remains++;
}
return 0;
@@ -665,7 +542,9 @@ static int hyper_new_container(char *json, int length)
}
list_add_tail(&c->list, &pod->containers);
ret = hyper_start_container_stage0(c, pod);
ret = hyper_setup_container(c, pod);
if (ret >= 0)
ret = hyper_run_process(&c->exec);
if (ret < 0) {
//TODO full grace cleanup
hyper_cleanup_container(c, pod);