diff --git a/flock/container.c b/flock/container.c index 8a5f6b78..2c0dcbe4 100644 --- a/flock/container.c +++ b/flock/container.c @@ -21,30 +21,25 @@ static struct hypervisor_container_forker { sock *s; pool *p; + struct cbor_stream *stream; struct birdloop *loop; HASH(struct container_runtime) hash; struct container_runtime *cur_crt; int ctl[2]; /* socketpair filedescriptors */ } hcf; -static struct container_config { - const char *hostname; - const char *workdir; - const char *basedir; -} ccf; +struct container_fork_request { + struct cbor_channel cch; + struct cbor_channel *ctl_ch; + struct container_runtime *crt; +}; struct container_runtime { struct container_runtime *next; - struct container_config ccf; uint hash; pid_t pid; sock *s; - struct container_operation_callback { - callback cb; - sock *s; - void *data; - } *ccc; - char data[]; + char hostname[]; }; #define CRT_KEY(c) c->ccf.hostname, c->hash @@ -289,7 +284,7 @@ container_init_logger(void) } static void -container_mainloop(int fd) +container_mainloop(int fd, struct flock_machine_container_config *ccf) { log(L_INFO "container mainloop with fd %d", fd); @@ -300,12 +295,12 @@ container_mainloop(int fd) /* Move to the workdir */ linpool *lp = lp_new(&root_pool); - if (strchr(ccf.basedir, ',') || - strchr(ccf.basedir, '=') || - strchr(ccf.basedir, '\\')) + if (strchr(ccf->basedir, ',') || + strchr(ccf->basedir, '=') || + strchr(ccf->basedir, '\\')) die("Refusing to work with paths containing chars: ,=\\"); - int wfd = GETDIR(lp_sprintf(lp, "%s%s", ccf.workdir[0] == '/' ? "" : "./", ccf.workdir)); + int wfd = GETDIR(lp_sprintf(lp, "%s%s", ccf->workdir[0] == '/' ? "" : "./", ccf->workdir)); SYSCALL(fchdir, wfd); close(wfd); wfd = -1; @@ -313,16 +308,16 @@ container_mainloop(int fd) close(GETDIR(lp_strdup(lp, "./tmp"))); close(GETDIR(lp_strdup(lp, "./root"))); - bool cloneroot = !strcmp(ccf.basedir, "/"); + bool cloneroot = !strcmp(ccf->basedir, "/"); bool clonedev = cloneroot; if (cloneroot) { - ccf.basedir = "./lower"; + ccf->basedir = "./lower"; close(GETDIR(lp_strdup(lp, "./lower"))); } const char *overlay_mount_options = lp_sprintf(lp, "lowerdir=%s,upperdir=%s,workdir=%s", - ccf.basedir, "./upper", "./tmp"); + ccf->basedir, "./upper", "./tmp"); SYSCALL(mount, "overlay", "./root", "overlay", 0, overlay_mount_options); if (cloneroot) @@ -531,10 +526,10 @@ container_mainloop(int fd) static uint container_counter = 0; static void -container_start(void) +container_start(struct flock_machine_container_config *ccf) { log(L_INFO "Requested to start a container, name %s, base %s, work %s", - ccf.hostname, ccf.basedir, ccf.workdir); + ccf->cf.name, ccf->basedir, ccf->workdir); pid_t pid = fork(); if (pid < 0) @@ -599,7 +594,7 @@ container_start(void) ASSERT_DIE(container_counter < 0x6000); this_thread_id -= (container_counter << 1) + 0x3000 ; - container_mainloop(fds[1]); /* this never returns */ + container_mainloop(fds[1], ccf); /* this never returns */ bug("container_mainloop has returned"); } @@ -757,6 +752,7 @@ hypervisor_container_forker_err(sock *sk, int e UNUSED) /* The child */ +#if 0 static void crt_err(sock *s, int err UNUSED) { @@ -799,92 +795,54 @@ container_created(callback *cb) mb_free(ccc); } +#endif void -hypervisor_container_request(sock *s, const char *name, const char *basedir, const char *workdir) +hypervisor_container_start(struct cbor_channel *cch, struct flock_machine_container_config *ccf) { birdloop_enter(hcf.loop); +// const char *name, const char *basedir, const char *workdir + const char *name = ccf->cf.name; uint h = mem_hash(name, strlen(name)); struct container_runtime *crt = HASH_FIND(hcf.hash, CRT, name, h); if (crt) { - struct { - struct cbor_writer w; - struct cbor_writer_stack_item si[2]; - } _cw; - - struct cbor_writer *cw = cbor_writer_init(&_cw.w, 2, s->tbuf, s->tbsize); - CBOR_PUT_MAP(cw) - { - cbor_put_int(cw, -127); - cbor_put_string(cw, "BAD: Already exists"); - } - - sk_send(s, cw->data.pos - cw->data.start); + CBOR_REPLY(cch, cw) + CBOR_PUT_MAP(cw) + { + cbor_put_int(cw, -127); + cbor_put_string(cw, "Container not created: Already exists"); + } + cbor_done_channel(cch); birdloop_leave(hcf.loop); return; } - uint nlen = strlen(name), - blen = strlen(basedir), - wlen = strlen(workdir); - - crt = mb_allocz(hcf.p, sizeof *crt + nlen + blen + wlen + 3); - - char *pos = crt->data; - - crt->ccf.hostname = pos; - memcpy(pos, name, nlen + 1); - pos += nlen + 1; - - crt->ccf.workdir = pos; - memcpy(pos, workdir, wlen + 1); - pos += wlen + 1; - - crt->ccf.basedir = pos; - memcpy(pos, basedir, blen + 1); - pos += blen + 1; - + uint nlen = strlen(name); + crt = mb_allocz(hcf.p, sizeof *crt + nlen + 1); crt->hash = h; - - struct container_operation_callback *ccc = mb_alloc(s->pool, sizeof *ccc); - *ccc = (struct container_operation_callback) { - .s = s, - .data = s->data, - }; - callback_init(&ccc->cb, container_created, s->loop); - crt->ccc = ccc; + memcpy(crt->hostname, name, nlen + 1); HASH_INSERT(hcf.hash, CRT, crt); - ASSERT_DIE(hcf.cur_crt == NULL); - hcf.cur_crt = crt; + log(L_INFO "requesting machine creation, name %s", name); + SKIP_BACK_DECLARE(struct container_fork_request, cfr, cch, cbor_channel_new(hcf.stream)); + cfr->crl_ch = cch; + cfr->crt = crt; + cfr->cch.parse = container_fork_request_reply; - log(L_INFO "requesting machine creation, socket %p", s); - - struct { - struct cbor_writer w; - struct cbor_writer_stack_item si[2]; - } _cw; - - struct cbor_writer *cw = cbor_writer_init(&_cw.w, 2, s->tbuf, s->tbsize); - CBOR_PUT_MAP(cw) - { - cbor_put_int(cw, 0); - cbor_put_string(cw, name); - cbor_put_int(cw, 1); - cbor_put_string(cw, basedir); - cbor_put_int(cw, 2); - cbor_put_string(cw, workdir); - } - - sk_send(s, cw->data.pos - cw->data.start); - - s->err_paused = crt_err; - s->data = crt; - sk_pause_rx(s->loop, s); + CBOR_REPLY(&cfr->cch, cw) + CBOR_PUT_MAP(cw) + { + cbor_put_int(cw, 0); + cbor_put_string(cw, name); + cbor_put_int(cw, 1); + cbor_put_string(cw, ccf->basedir); + cbor_put_int(cw, 2); + cbor_put_string(cw, ccf->workdir); + } birdloop_leave(hcf.loop); } @@ -916,58 +874,45 @@ container_stopped(callback *cb) } void -hypervisor_container_shutdown(sock *s, const char *name) +hypervisor_container_shutdown(struct cbor_channel *cch, struct flock_machine_container_config *ccf) { birdloop_enter(hcf.loop); + const char *name = ccf->cf.name; uint h = mem_hash(name, strlen(name)); struct container_runtime *crt = HASH_FIND(hcf.hash, CRT, name, h); if (!crt || !crt->s) { - struct { - struct cbor_writer w; - struct cbor_writer_stack_item si[2]; - } _cw; + CBOR_REPLY(cch, cw) + CBOR_PUT_MAP(cw) + { + cbor_put_int(cw, -127); + cbor_put_string(cw, "BAD: Not found"); + } - struct cbor_writer *cw = cbor_writer_init(&_cw.w, 2, s->tbuf, s->tbsize); - CBOR_PUT_MAP(cw) - { - cbor_put_int(cw, -127); - cbor_put_string(cw, "BAD: Not found"); - } - - sk_send(s, cw->data.pos - cw->data.start); + cbor_done_channel(cch); birdloop_leave(hcf.loop); return; } - struct { - struct cbor_writer w; - struct cbor_writer_stack_item si[2]; - } _cw; + struct cbor_channel *xch = cbor_channel_new(crt->stream); + CBOR_REPLY(xch, cw) + CBOR_PUT_MAP(cw) + { + cbor_put_int(cw, 0); + cbor_put_null(cw); + } - struct cbor_writer *cw = cbor_writer_init(&_cw.w, 2, s->tbuf, s->tbsize); - CBOR_PUT_MAP(cw) - { - cbor_put_int(cw, 0); - cbor_put_null(cw); - } - - sk_send(s, cw->data.pos - cw->data.start); - - struct container_operation_callback *ccc = mb_alloc(s->pool, sizeof *ccc); + struct container_operation_callback *ccc = mb_alloc(cch->pool, sizeof *ccc); *ccc = (struct container_operation_callback) { - .s = s, - .data = s->data, + .cch = cch, + .ccf = ccf, + .cancel = container_operation_hangup, }; callback_init(&ccc->cb, container_stopped, s->loop); crt->ccc = ccc; - s->err_paused = crt_err; - s->data = crt; - sk_pause_rx(s->loop, s); - birdloop_leave(hcf.loop); } diff --git a/flock/ctl.c b/flock/ctl.c index f55bf333..d633b740 100644 --- a/flock/ctl.c +++ b/flock/ctl.c @@ -22,6 +22,7 @@ struct hcs_parser_context { struct cbor_parser_context *ctx; struct cbor_stream *stream; + struct hcs_parser_channel *channel; sock *sock; u64 bytes_consumed; @@ -44,30 +45,25 @@ struct hcs_parser_channel { }; static void -//hcs_request_poweroff(struct hcs_parser_channel *hpc) -hcs_request_poweroff(struct hcs_parser_context *htx) +hcs_request_poweroff(struct hcs_parser_channel *hpc) { log(L_INFO "Requested shutdown via CLI"); ev_send_loop(&main_birdloop, &poweroff_event); - struct { - struct cbor_writer w; - struct cbor_writer_stack_item si[2]; - } _cw; + CBOR_REPLY(&hpc->cch, cw) + CBOR_PUT_MAP(cw) + { + cbor_put_int(cw, -1); + cbor_put_string(cw, "OK"); + } - struct cbor_writer *cw = cbor_writer_init(&_cw.w, 2, htx->sock->tbuf, htx->sock->tbsize); - CBOR_PUT_MAP(cw) - { - cbor_put_int(cw, -1); - cbor_put_string(cw, "OK"); - } - - sk_send(htx->sock, cw->data.pos - cw->data.start); + cbor_done_channel(&hpc->cch); } static void -hcs_get_telnet(struct hcs_parser_context *htx) +hcs_get_telnet(struct hcs_parser_channel *hpc) { +// TODO: hexp_get_telnet(); } struct hcs_parser_context * @@ -93,18 +89,21 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) { ASSERT_DIE(size > 0); struct cbor_parser_context *ctx = htx->ctx; + struct hcs_parser_channel *hpc = htx->channel; + + bool finish_cmd = false; for (int pos = 0; pos < size; pos++) { - /* - if (!htx->channel) + if (!hpc) { - htx->channel = cbor_parse_channel(ctx, htx->stream, buf[pos]); - if (htx->channel == &cbor_channel_parse_error) + struct cbor_channel *cch = cbor_parse_channel(ctx, htx->stream, buf[pos]); + if (cch == &cbor_channel_parse_error) return -(htx->bytes_consumed + pos + 1); + else if (cch) + hpc = htx->channel = SKIP_BACK(struct hcs_parser_channel, cch, cch); continue; } - */ switch (cbor_parse_byte(ctx, buf[pos])) { @@ -120,42 +119,31 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) /* Check type acceptance */ switch (htx->major_state) { - case 0: /* toplevel */ - if (ctx->type != 4) - CBOR_PARSER_ERROR("Expected array, got %u", ctx->type); + case 0: /* Command */ + CBOR_PARSE_ONLY(ctx, POSINT, hpc->cmd); + if (hpc->cmd > HCS_CMD__MAX) + CBOR_PARSER_ERROR("Command key too high, got %lu", hpc->cmd); - if (ctx->value != 3) - CBOR_PARSER_ERROR("Expected array of length 1, got %u", ctx->value); - - htx->major_state = 1; - break; - - case 1: /* Command */ - CBOR_PARSE_ONLY(ctx, POSINT, htx->cmd); - if (htx->cmd > HCS_CMD__MAX) - CBOR_PARSER_ERROR("Command key too high, got %lu", htx->cmd); - - htx->major_state = htx->cmd + 10; + htx->major_state = hpc->cmd + 10; break; case HCS_CMD_SHUTDOWN + 10: /* shutdown command: expected null */ if ((ctx->type != 7) || (ctx->value != 22)) CBOR_PARSER_ERROR("Expected null, got %u-%u", ctx->type, ctx->value); - hcs_request_poweroff(htx); - - htx->major_state = 3; + hcs_request_poweroff(hpc); + finish_cmd = true; break; case HCS_CMD_TELNET + 10: /* telnet listener open */ if ((ctx->type == 7) && (ctx->value == 22)) { - hcs_get_telnet(htx); - htx->major_state = 3; + hcs_get_telnet(hpc); + finish_cmd = true; break; } - else CBOR_PARSE_IF(ctx, TEXT, htx->cfg.cf.name) + else CBOR_PARSE_IF(ctx, TEXT, hpc->cfg.cf.name) ; else CBOR_PARSER_ERROR("Expected null or string, got %s", cbor_type_str(ctx->type)); @@ -189,11 +177,11 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) break; case 502: /* machine creation argument 0: name */ - CBOR_PARSE_ONLY(ctx, TEXT, htx->cfg.cf.name); + CBOR_PARSE_ONLY(ctx, TEXT, hpc->cfg.cf.name); break; case 503: /* machine creation argument 1: type */ - CBOR_PARSE_ONLY(ctx, POSINT, htx->cfg.cf.type); + CBOR_PARSE_ONLY(ctx, POSINT, hpc->cfg.cf.type); if ((ctx->value < 1) && (ctx->value > 1) ) CBOR_PARSER_ERROR("Unexpected type, got %lu", ctx->value); @@ -202,11 +190,11 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) break; case 504: /* machine creation argument 2: basedir */ - CBOR_PARSE_ONLY(ctx, BYTES, htx->cfg.container.basedir); + CBOR_PARSE_ONLY(ctx, BYTES, hpc->cfg.container.basedir); break; case 505: /* machine creation argument 3: workdir */ - CBOR_PARSE_ONLY(ctx, BYTES, htx->cfg.container.workdir); + CBOR_PARSE_ONLY(ctx, BYTES, hpc->cfg.container.workdir); break; case 601: /* machine shutdown argument */ @@ -219,7 +207,7 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) break; case 602: /* machine creation argument 0: name */ - CBOR_PARSE_ONLY(ctx, TEXT, htx->cfg.cf.name); + CBOR_PARSE_ONLY(ctx, TEXT, hpc->cfg.cf.name); break; default: @@ -231,9 +219,9 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) /* Bytes read completely! */ switch (htx->major_state) { - case 3: - hexp_get_telnet(htx->sock, htx->cfg.cf.name); - htx->major_state = 1; + case HCS_CMD_TELNET + 10: + hcs_get_telnet(hpc); + finish_cmd = true; break; case 502: @@ -253,6 +241,19 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) break; } + if (finish_cmd) + { + finish_cmd = false; + + if (!cbor_parse_channel_finish(ctx, htx->stream)) + CBOR_PARSER_ERROR("Failed to finish CBOR channel parser"); + + htx->channel = NULL; + htx->bytes_consumed = 0; + htx->major_state = 0; + continue; + } + /* End of array or map */ while (cbor_parse_block_end(ctx)) { @@ -274,33 +275,39 @@ hcs_parse(struct hcs_parser_context *htx, const byte *buf, s64 size) break; case 501: - if (!htx->cfg.cf.type) + /* + if (!hpc->cfg.cf.type) CBOR_PARSER_ERROR("Machine type not specified"); - if (!htx->cfg.cf.name) + if (!hpc->cfg.cf.name) CBOR_PARSER_ERROR("Machine name not specified"); - if (!htx->cfg.container.workdir) + if (!hpc->cfg.container.workdir) CBOR_PARSER_ERROR("Machine workdir not specified"); - if (!htx->cfg.container.basedir) + if (!hpc->cfg.container.basedir) CBOR_PARSER_ERROR("Machine basedir not specified"); hypervisor_container_request( htx->sock, - htx->cfg.cf.name, - htx->cfg.container.basedir, - htx->cfg.container.workdir); + hpc->cfg.cf.name, + hpc->cfg.container.basedir, + hpc->cfg.container.workdir); + */ + hypervisor_container_start(&hpc->cch, &hpc->cfg.container); htx->major_state = 1; break; case 601: + /* if (!htx->cfg.cf.name) CBOR_PARSER_ERROR("Machine name not specified"); hypervisor_container_shutdown(htx->sock, htx->cfg.cf.name); + */ + hypervisor_container_shutdown(&hpc->cch, &hpc->cfg.container); htx->major_state = 1; break; diff --git a/flock/flock.h b/flock/flock.h index d2041ccc..5af84cf1 100644 --- a/flock/flock.h +++ b/flock/flock.h @@ -5,6 +5,7 @@ #ifndef INCLUDE_FLOCK_H #define INCLUDE_FLOCK_H #include "lib/birdlib.h" +#include "lib/cbor.h" #include "lib/event.h" #include "lib/obstacle.h" #include "lib/resource.h" @@ -45,9 +46,8 @@ union flock_machine_config { } container; }; - -void hypervisor_container_request(sock *s, const char *name, const char *basedir, const char *workdir); -void hypervisor_container_shutdown(sock *s, const char *name); +void hypervisor_container_start(struct cbor_channel *, struct flock_machine_container_config *); +void hypervisor_container_shutdown(struct cbor_channel *, struct flock_machine_container_config *); int container_ctl_fd(const char *name); void hexp_cleanup_after_fork(void);