0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Flock: Stopping containers from CLI

This commit is contained in:
Maria Matejka 2024-09-27 20:09:51 +02:00
parent f1519fc9b7
commit d36ad6af6a
4 changed files with 188 additions and 15 deletions

View File

@ -31,7 +31,7 @@ struct container_runtime {
uint hash;
pid_t pid;
sock *s;
struct container_created_callback {
struct container_operation_callback {
callback cb;
sock *s;
void *data;
@ -60,6 +60,19 @@ container_child_sighandler(int signo UNUSED)
static int container_forker_fd = -1;
static void
container_poweroff(int fd, int sig)
{
byte outbuf[128];
linpool *lp = lp_new(&root_pool);
struct cbor_writer *cw = cbor_init(outbuf, sizeof outbuf, lp);
cbor_open_block_with_length(cw, 1);
cbor_add_int(cw, -4);
cbor_add_int(cw, sig);
ASSERT_DIE(write(fd, outbuf, cw->pt) == cw->pt);
exit(0);
}
static void
container_mainloop(int fd)
{
@ -83,15 +96,27 @@ container_mainloop(int fd)
int res = ppoll(&pfd, 1, NULL, &newmask);
if (poweroff)
container_poweroff(fd, poweroff);
if (pfd.revents & POLLIN)
{
byte outbuf[128];
linpool *lp = lp_new(&root_pool);
struct cbor_writer *cw = cbor_init(outbuf, sizeof outbuf, lp);
cbor_open_block_with_length(cw, 1);
cbor_add_int(cw, -4);
cbor_add_int(cw, poweroff);
ASSERT_DIE(write(fd, outbuf, cw->pt) == cw->pt);
exit(0);
byte buf[128];
ssize_t sz = read(fd, buf, sizeof buf);
if (sz < 0)
{
log(L_ERR "error reading data from control socket: %m");
exit(1);
}
ASSERT_DIE(sz >= 3);
ASSERT_DIE(buf[0] == 0xa1);
switch (buf[1]) {
case 0:
ASSERT_DIE(buf[2] == 0xf6);
container_poweroff(fd, 0);
break;
}
}
/* TODO: check for telnet socket */
@ -203,6 +228,14 @@ container_start(void)
/* The Parent */
static void
container_cleanup(struct container_runtime *crt)
{
HASH_REMOVE(hcf.hash, CRT, crt);
sk_close(crt->s);
mb_free(crt);
}
static int
hypervisor_container_rx(sock *sk, uint _sz UNUSED)
{
@ -215,7 +248,25 @@ hypervisor_container_rx(sock *sk, uint _sz UNUSED)
return 0;
}
log(L_INFO "received %u data from %p (container_rx)", sz, sk);
struct container_runtime *crt = sk->data;
ASSERT_DIE(crt->s == sk);
ASSERT_DIE(sz >= 3);
ASSERT_DIE(buf[0] == 0xa1);
switch (buf[1]) {
case 0x23:
log(L_INFO "container %s ended by signal %d", crt->ccf.hostname, buf[2]);
if (crt->ccc)
callback_activate(&crt->ccc->cb);
container_cleanup(crt);
break;
default:
log(L_ERR "container %s sent a weird message 0x%02x sz %d", crt->ccf.hostname, buf[1], sz);
break;
}
return 0;
}
@ -267,18 +318,23 @@ hypervisor_container_forker_rx(sock *sk, uint _sz UNUSED)
skl->type = SK_MAGIC;
skl->rx_hook = hypervisor_container_rx;
skl->fd = sfd;
sk_set_tbsize(skl, 1024);
if (sk_open(skl, sk->loop) < 0)
bug("Machine control socket: sk_open failed");
ASSERT_DIE(birdloop_inside(hcf.loop));
ASSERT_DIE(hcf.cur_crt);
skl->data = hcf.cur_crt;
hcf.cur_crt->pid = pid;
hcf.cur_crt->s = skl;
if (hcf.cur_crt->ccc)
callback_activate(&hcf.cur_crt->ccc->cb);
hcf.cur_crt->ccc = NULL;
hcf.cur_crt = NULL;
return 0;
}
@ -303,8 +359,8 @@ crt_err(sock *s, int err UNUSED)
static void
container_created(callback *cb)
{
SKIP_BACK_DECLARE(struct container_created_callback, ccc, cb, cb);
SKIP_BACK_DECLARE(struct container_operation_callback, ccc, cb, cb);
sock *s = ccc->s;
linpool *lp = lp_new(s->pool);
struct cbor_writer *cw = cbor_init(s->tbuf, s->tbsize, lp);
@ -363,8 +419,8 @@ hypervisor_container_request(sock *s, const char *name, const char *basedir, con
crt->hash = h;
struct container_created_callback *ccc = mb_alloc(s->pool, sizeof *ccc);
*ccc = (struct container_created_callback) {
struct container_operation_callback *ccc = mb_alloc(s->pool, sizeof *ccc);
*ccc = (struct container_operation_callback) {
.s = s,
.data = s->data,
};
@ -397,6 +453,72 @@ hypervisor_container_request(sock *s, const char *name, const char *basedir, con
birdloop_leave(hcf.loop);
}
static void
container_stopped(callback *cb)
{
SKIP_BACK_DECLARE(struct container_operation_callback, ccc, cb, cb);
sock *s = ccc->s;
linpool *lp = lp_new(s->pool);
struct cbor_writer *cw = cbor_init(s->tbuf, s->tbsize, lp);
cbor_open_block_with_length(cw, 1);
cbor_add_int(cw, -1);
cbor_add_string(cw, "OK");
sk_send(s, cw->pt);
rfree(lp);
s->data = ccc->data;
sk_resume_rx(s->loop, s);
mb_free(ccc);
}
void
hypervisor_container_shutdown(sock *s, const char *name)
{
birdloop_enter(hcf.loop);
uint h = mem_hash(name, strlen(name));
struct container_runtime *crt = HASH_FIND(hcf.hash, CRT, name, h);
linpool *lp = lp_new(hcf.p);
if (!crt || !crt->s)
{
struct cbor_writer *cw = cbor_init(s->tbuf, s->tbsize, lp);
cbor_open_block_with_length(cw, 1);
cbor_add_int(cw, -127);
cbor_add_string(cw, "BAD: Not found");
sk_send(s, cw->pt);
rfree(lp);
birdloop_leave(hcf.loop);
return;
}
struct cbor_writer *cw = cbor_init(crt->s->tbuf, crt->s->tbsize, lp);
cbor_open_block_with_length(cw, 1);
cbor_add_int(cw, 0);
write_item(cw, 7, 22);
sk_send(crt->s, cw->pt);
rfree(lp);
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_stopped, s->loop);
crt->ccc = ccc;
s->err_paused = crt_err;
s->data = crt;
sk_pause_rx(s->loop, s);
birdloop_leave(hcf.loop);
}
struct cbor_parser_context {
linpool *lp;

View File

@ -212,7 +212,14 @@ hcs_parse(struct cbor_parser_context *ctx, const byte *buf, s64 size)
ctx->major_state = 501;
break;
case 6: /* process spawner */
case 6: /* machine shutdown request */
if (ctx->type != 5)
CBOR_PARSER_ERROR("Expecting mapping, got %u", ctx->type);
ctx->major_state = 601;
break;
case 7: /* process spawner */
CBOR_PARSER_ERROR("NOT IMPLEMENTED YET");
break;
@ -285,6 +292,31 @@ hcs_parse(struct cbor_parser_context *ctx, const byte *buf, s64 size)
ctx->target_len = ctx->value;
break;
case 601: /* machine shutdown argument */
if (ctx->type != 0)
CBOR_PARSER_ERROR("Expected integer, got %u", ctx->type);
if (ctx->value >= 1)
CBOR_PARSER_ERROR("Command key too high, got %lu", ctx->value);
ctx->major_state = ctx->value + 602;
break;
case 602: /* machine creation argument 0: name */
if (ctx->type != 3)
CBOR_PARSER_ERROR("Expected string, got %u", ctx->type);
if (value_is_special)
CBOR_PARSER_ERROR("Variable length string not supported yet");
if (ctx->cfg.cf.name)
CBOR_PARSER_ERROR("Duplicate argument 0 / name");
ASSERT_DIE(!ctx->target_buf);
ctx->cfg.cf.name = ctx->target_buf = lp_alloc(ctx->lp, ctx->value + 1);
ctx->target_len = ctx->value;
break;
default:
bug("invalid parser state");
}
@ -342,6 +374,10 @@ hcs_parse(struct cbor_parser_context *ctx, const byte *buf, s64 size)
ctx->major_state = 501;
break;
case 602:
ctx->major_state = 601;
break;
default:
bug("Unexpected state to end a (byte)string in");
/* Code to run at the end of a (byte)string */
@ -395,6 +431,15 @@ hcs_parse(struct cbor_parser_context *ctx, const byte *buf, s64 size)
ctx->major_state = 1;
break;
case 601:
if (!ctx->cfg.cf.name)
CBOR_PARSER_ERROR("Machine name not specified");
hypervisor_container_shutdown(ctx->sock, ctx->cfg.cf.name);
ctx->major_state = 1;
break;
default:
bug("Unexpected state to end a mapping in");
}

View File

@ -100,6 +100,11 @@ def container_start(hypervisor: str, name: str):
}}).items():
print(k,v)
@handler
def container_stop(hypervisor: str, name: str):
for k,v in msg(hypervisor, { 4: { 0: name, }}).items():
print(k,v)
try:
binname = sys.argv.pop(0)
except Exception as e:

View File

@ -47,6 +47,7 @@ union flock_machine_config {
void hypervisor_container_request(sock *s, const char *name, const char *basedir, const char *workdir);
void hypervisor_container_shutdown(sock *s, const char *name);
extern event reboot_event, poweroff_event;
extern event_list shutdown_event_list;