diff --git a/src/hyper.h b/src/hyper.h index 215eb72..b3ed4c9 100644 --- a/src/hyper.h +++ b/src/hyper.h @@ -27,6 +27,7 @@ enum { NEXT, WRITEFILE, READFILE, + NEWCONTAINER, }; enum { @@ -43,7 +44,7 @@ struct hyper_pod { struct list_head exec_head; //struct list_head ce_head; char *hostname; - char *tag; + char *share_tag; int init_pid; uint32_t c_num; uint32_t i_num; diff --git a/src/init.c b/src/init.c index 97ed41e..eb078f1 100644 --- a/src/init.c +++ b/src/init.c @@ -349,16 +349,24 @@ fail: goto out; } -static int hyper_do_start_containers(void *data) +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 i, pidns, ipcns, utsns, ret; + int pidns, ipcns, utsns, ret; struct hyper_container *c; - struct hyper_pod_arg *arg; + 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; @@ -390,15 +398,7 @@ static int hyper_do_start_containers(void *data) goto out; } - for (i = 0; i < pod->c_num; i++) { - c = &pod->c[i]; - if (hyper_start_container(c, utsns, ipcns, pod) < 0) { - fprintf(stderr, "fail to start container\n"); - goto out; - } - } - - ret = 0; + ret = hyper_start_container(c, utsns, ipcns, pod); out: if (hyper_send_type(arg->ctl_pipe[1], ret ? ERROR : READY) < 0) { fprintf(stderr, "container init send ready message failed\n"); @@ -413,12 +413,13 @@ out: _exit(ret); } -int hyper_start_containers(struct hyper_pod *pod) +int hyper_start_container_stage0(struct hyper_container *c, struct hyper_pod *pod) { int stacksize = getpagesize() * 4; void *stack = NULL; - struct hyper_pod_arg arg = { + struct hyper_stage0_arg arg = { .pod = pod, + .container = c, .ctl_pipe = {-1, -1}, }; int ret = -1, pid; @@ -436,7 +437,7 @@ int hyper_start_containers(struct hyper_pod *pod) goto out; } - pid = clone(hyper_do_start_containers, stack + stacksize, CLONE_VM| CLONE_FILES| SIGCHLD, &arg); + pid = clone(hyper_container_stage0, stack + stacksize, CLONE_VM| CLONE_FILES| SIGCHLD, &arg); free(stack); if (pid < 0) { perror("enter container pid ns failed"); @@ -462,6 +463,18 @@ out: return ret; } +int hyper_start_containers(struct hyper_pod *pod) +{ + int i, ret = 0; + + for (i = 0; i < pod->c_num; i++) { + ret = hyper_start_container_stage0(&pod->c[i], pod); + if (ret) + return ret; + } + return 0; +} + static int hyper_setup_container(struct hyper_pod *pod) { int stacksize = getpagesize() * 4; @@ -555,7 +568,7 @@ static int hyper_setup_shared(struct hyper_pod *pod) { struct vbsf_mount_info_new mntinf; - if (pod->tag == NULL) { + if (pod->share_tag == NULL) { fprintf(stdout, "no shared directroy\n"); return 0; } @@ -573,7 +586,7 @@ static int hyper_setup_shared(struct hyper_pod *pod) mntinf.length = sizeof(mntinf); mntinf.dmode = ~0U; mntinf.fmode = ~0U; - strcpy(mntinf.name, pod->tag); + strcpy(mntinf.name, pod->share_tag); if (mount(NULL, "/tmp/hyper/shared", "vboxsf", MS_NODEV, &mntinf) < 0) { @@ -586,7 +599,7 @@ static int hyper_setup_shared(struct hyper_pod *pod) #else static int hyper_setup_shared(struct hyper_pod *pod) { - if (pod->tag == NULL) { + if (pod->share_tag == NULL) { fprintf(stdout, "no shared directroy\n"); return 0; } @@ -596,7 +609,7 @@ static int hyper_setup_shared(struct hyper_pod *pod) return -1; } - if (mount(pod->tag, "/tmp/hyper/shared", "9p", + if (mount(pod->share_tag, "/tmp/hyper/shared", "9p", MS_MGC_VAL| MS_NODEV, "trans=virtio,cache=loose") < 0) { perror("fail to mount shared dir"); @@ -674,6 +687,32 @@ static int hyper_start_pod(char *json, int length) return 0; } +static int hyper_new_container(char *json, int length) +{ + int ret; + struct hyper_pod *pod = &global_pod; + + fprintf(stdout, "call hyper_new_container, json %s, len %d\n", json, length); + + if (!pod->init_pid) + fprintf(stdout, "the pod is not created yet\n"); + + if (hyper_parse_new_container(pod, json, length) < 0) { + fprintf(stderr, "parse container json failed\n"); + return -1; + } + + ret = hyper_start_container_stage0(&pod->c[pod->c_num - 1], pod); + if (ret < 0) { + //TODO full grace cleanup + pod->remains -= 1; + pod->c_num -= 1; + return ret; + } + + return 0; +} + static int hyper_cmd_write_file(char *json, int length) { struct hyper_writter writter; @@ -917,16 +956,16 @@ static void hyper_cleanup_hostname(struct hyper_pod *pod) static void hyper_cleanup_shared(struct hyper_pod *pod) { - if (pod->tag == NULL) { + if (pod->share_tag == NULL) { fprintf(stdout, "no shared directroy\n"); return; } - free(pod->tag); - pod->tag = NULL; + free(pod->share_tag); + pod->share_tag = NULL; if (umount("/tmp/hyper/shared") < 0 && umount2("/tmp/hyper/shared", MNT_DETACH)) { - perror("fail to umount 9p dir"); + perror("fail to umount shared dir"); return; } @@ -1099,6 +1138,9 @@ static int hyper_channel_handle(struct hyper_event *de, uint32_t len) case WINSIZE: ret = hyper_set_win_size((char *)buf->data + 8, len - 8); break; + case NEWCONTAINER: + ret = hyper_new_container((char *)buf->data + 8, len - 8); + break; default: ret = -1; break; diff --git a/src/parse.c b/src/parse.c index dfb11e3..113852b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -510,8 +510,8 @@ realloc: i += next; } else if (json_token_streq(json, t, "shareDir") && t->size == 1) { - pod->tag = strdup(json_token_str(json, &toks[++i])); - fprintf(stdout, "9p tag is %s\n", pod->tag); + pod->share_tag = strdup(json_token_str(json, &toks[++i])); + fprintf(stdout, "share tag is %s\n", pod->share_tag); } else if (json_token_streq(json, t, "hostname") && t->size == 1) { pod->hostname = strdup(json_token_str(json, &toks[++i])); fprintf(stdout, "hostname is %s\n", pod->hostname); @@ -530,6 +530,51 @@ out: return next; } +int hyper_parse_new_container(struct hyper_pod *pod, char *json, int length) +{ + int n; + jsmn_parser p; + int toks_num = 100; + jsmntok_t *toks = NULL; + struct hyper_container *c; + +realloc: + toks = realloc(toks, toks_num * sizeof(jsmntok_t)); + + jsmn_init(&p); + n = jsmn_parse(&p, json, length, toks, toks_num); + if (n < 0) { + fprintf(stdout, "jsmn parse failed, n is %d\n", n); + if (n == JSMN_ERROR_NOMEM) { + toks_num *= 2; + goto realloc; + } + + goto fail; + } + + c = realloc(pod->c, (pod->c_num + 1) * sizeof(*pod->c)); + if (c == NULL) { + fprintf(stdout, "alloc memory for container failed\n"); + goto fail; + } + pod->c = c; + memset(&pod->c[pod->c_num], 0, sizeof(pod->c[pod->c_num])); + + // trick: toks-1, TODO: change all "i = 1" to "i = 0" + if (hyper_parse_container(pod, &pod->c[pod->c_num], json, toks-1) < 0) + goto fail; + + pod->remains += 1; + pod->c_num += 1; + free(toks); + return 0; + +fail: + free(toks); + return -1; +} + int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length) { int i, n, ret = 0;