]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Container runner basics
authorMaria Matejka <mq@ucw.cz>
Mon, 16 Sep 2024 20:48:49 +0000 (22:48 +0200)
committerMaria Matejka <mq@ucw.cz>
Sun, 23 Feb 2025 18:07:35 +0000 (19:07 +0100)
flock/container.c
flock/hypervisor.c

index f062095e58fc7ec46cc86b6fb02f74f4e4b1d93e..47a8c8e213b0a93e7e0338d36ef490538de475b9 100644 (file)
 
 #include <stdlib.h>
 
+static void
+container_mainloop(struct flock_machine_container_config *cfg, int fd)
+{
+  log(L_INFO "container mainloop");
+  /* TODO cleanup the loops from the forked process */
+  while (1)
+  {
+    pause();
+    log(L_INFO "woken up!");
+  }
+}
+
+struct container_start_callback {
+  callback cb;
+  sock *s, *skm;
+  struct birdloop *loop;
+  pool *pool;
+
+  /* Stored socket hooks */
+  int (*rx_hook)(sock *, uint size);
+  void (*err_hook)(sock *, int);
+  void *data;
+
+  /* Actual config */
+  struct flock_machine_container_config cfg;
+};
+
+static void
+container_start_sk_err(sock *s, int e)
+{
+  struct container_start_callback *cb = s->data;
+
+  cb->skm->data = NULL;
+  s->data = cb->data;
+  s->err_hook = cb->err_hook;
+
+  mb_free(cb);
+  s->err_hook(s, e);
+}
+
+static int
+container_parent_rx(sock *skm, uint size)
+{
+  bug("container_parent_rx");
+  ASSERT_DIE(size >= 3);
+
+  ASSERT_DIE(skm->rbuf[0] == 0xa1);
+
+  switch (skm->rbuf[1])
+  {
+    case 0:
+      {
+       pid_t pid;
+       if (skm->rbuf[2] < 24)
+         pid = skm->rbuf[2];
+       else if (skm->rbuf[2] == 24)
+         pid = skm->rbuf[3];
+       else if (skm->rbuf[2] == 25)
+         pid = skm->rbuf[3] << 8 + skm->rbuf[4];
+       else if (skm->rbuf[3] == 26)
+         pid = skm->rbuf[3] << 32 + skm->rbuf[4] << 24 + skm->rbuf[5] << 16 + skm->rbuf[6];
+       else
+         bug("not implemented");
+
+       log(L_INFO "Machine started with PID %d", pid);
+
+       if (!skm->data)
+         return 1;
+
+       struct container_start_callback *cb = skm->data;
+       struct linpool *lp = lp_new(cb->s->pool);
+       struct cbor_writer *cw = cbor_init(cb->s->tbuf, cb->s->tbsize, lp);
+       cbor_open_block_with_length(cw, 1);
+       cbor_add_int(cw, -1);
+       cbor_add_string(cw, "OK");
+       sk_send(cb->s, cw->pt);
+       rfree(lp);
+
+       cb->s->data = cb->data;
+       cb->s->err_hook = cb->err_hook;
+       sk_resume_rx(cb->s->loop, cb->s, cb->rx_hook);
+
+       mb_free(cb);
+       return 1;
+      }
+
+    default:
+      bug("unimplemented");
+  }
+
+  return 1;
+}
+
+static void
+container_parent_err(sock *s, int e)
+{
+  log(L_ERR "Container parent error hook not implemented: %d (%s)", e, strerror(e));
+  sk_close(s);
+}
+
+static void
+container_start_callback(struct callback *_cb)
+{
+  SKIP_BACK_DECLARE(struct container_start_callback, cb, cb, _cb);
+
+  ASSERT_DIE(birdloop_inside(&main_birdloop));
+
+  log(L_INFO "Requested to start a container, name %s, base %s, work %s",
+      cb->cfg.cf.name, cb->cfg.basedir, cb->cfg.workdir);
+
+  /* create socketpair before forking to do communication */
+  int fds[2];
+  int e = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+  if (e < 0)
+    die("Failed to create internal socketpair: %m");
+
+  pid_t pid = fork();
+  if (pid < 0)
+    die("Failed to fork exposed: %m");
+
+  if (!pid)
+  {
+    close(fds[0]);
+    container_mainloop(&cb->cfg, fds[1]); /* this never returns */
+    bug("container_mainloop has returned");
+  }
+
+  close(fds[1]);
+
+  birdloop_enter(cb->loop);
+  sock *skm = sk_new(cb->pool);
+  skm->type = SK_MAGIC;
+  skm->fd = fds[0];
+  skm->rx_hook = container_parent_rx;
+  skm->err_hook = container_parent_err;
+  skm->data = cb;
+  cb->skm = skm;
+
+  if (sk_open(skm, cb->loop) < 0)
+    bug("Container listener: sk_open failed");
+
+  birdloop_leave(cb->loop);
+}
+
 void
 container_start(struct birdsock *s, struct flock_machine_container_config *cfg)
 {
-  log(L_INFO "Requested to start a container, name %s, base %s, work %s",
-      cfg->cf.name, cfg->basedir, cfg->workdir);
-
-  struct 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);
+  struct container_start_callback *cb = mb_alloc(s->pool, sizeof *cb);
+  *cb = (struct container_start_callback) {
+    .cb = callback_init(&cb->cb, container_start_callback, &main_birdloop),
+    .s = s,
+    .loop = s->loop,
+    .pool = s->pool,
+    .rx_hook = s->rx_hook,
+    .err_hook = s->err_hook,
+    .data = s->data,
+    .cfg = *cfg,
+  };
+
+  sk_pause_rx(s->loop, s);
+  s->err_hook = container_start_sk_err;
+  s->data = cb;
+
+  callback_activate(&cb->cb);
 }
index d69959ccbb0698b234985c73e3c27fb982781686..2fa701c9d8be60ac36430d62055f488a1098ee52 100644 (file)
@@ -510,7 +510,7 @@ hexp_get_telnet(sock *s, const char *name)
     rfree(lp);
   }
 
-  s->rx_hook = NULL;
+  sk_pause_rx(s->loop, s);
   s->err_hook = hexp_sock_err;
 
   struct hexp_telnet_requestor *req = mb_allocz(hcs_pool, sizeof *req);
@@ -537,7 +537,7 @@ static void hexp_received_telnet(void *_data)
 
   WALK_TLIST_DELSAFE(hexp_telnet_requestor, r, &hrt->p->requestors)
   {
-    r->s->rx_hook = hcs_rx;
+    sk_resume_rx(r->s->loop, r->s, hcs_rx);
     r->s->err_hook = hcs_err;
     memcpy(r->s->tbuf, outbuf, cw->pt);
     sk_send(r->s, cw->pt);