lxc/0009-lxc_start-add-default-terminal-fifos.patch
LiFeng c1c967d9bc lxc: make lxc-libs package
Signed-off-by: LiFeng <lifeng68@huawei.com>
2020-02-14 06:13:22 -05:00

539 lines
15 KiB
Diff

From d96fee01aeb6f95f5b017f5d8828e1994c549dc5 Mon Sep 17 00:00:00 2001
From: LiFeng <lifeng68@huawei.com>
Date: Fri, 11 Jan 2019 21:52:11 -0500
Subject: [PATCH 009/139] lxc_start: add default terminal fifos
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/conf.c | 4 +
src/lxc/lxccontainer.c | 30 +++++++
src/lxc/lxccontainer.h | 10 +++
src/lxc/terminal.c | 194 +++++++++++++++++++++++++++++++++++++++++++++-
src/lxc/terminal.h | 16 ++++
src/lxc/tools/arguments.h | 5 ++
src/lxc/tools/lxc_start.c | 11 +++
src/lxc/utils.c | 23 ++++++
src/lxc/utils.h | 4 +
9 files changed, 294 insertions(+), 3 deletions(-)
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 37a5ff7..7b7f95b 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2714,6 +2714,10 @@ struct lxc_conf *lxc_conf_init(void)
new->console.slave = -1;
new->console.name[0] = '\0';
memset(&new->console.ringbuf, 0, sizeof(struct lxc_ringbuf));
+ /* isulad init console fifos */
+ new->console.init_fifo[0] = NULL;
+ new->console.init_fifo[1] = NULL;
+ lxc_list_init(&new->console.fifos);
new->maincmd_fd = -1;
new->nbd_idx = -1;
new->rootfs.mount = strdup(default_rootfs_mount);
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 1d7f5be..318c71e 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -4961,6 +4961,33 @@ out:
return ret;
}
+/* isulad add set console fifos*/
+static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out)
+{
+ struct lxc_conf *conf;
+
+ if (!c || !c->lxc_conf || !in || !out)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ conf = c->lxc_conf;
+ if (conf->console.init_fifo[0])
+ free(conf->console.init_fifo[0]);
+ conf->console.init_fifo[0] = strdup(in);
+
+ if (conf->console.init_fifo[1])
+ free(conf->console.init_fifo[1]);
+ conf->console.init_fifo[1] = strdup(out);
+
+ container_mem_unlock(c);
+ return true;
+}
+
+WRAP_API_2(bool, lxcapi_set_terminal_default_fifos, const char *, const char *)
+
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
{
struct lxc_container *c;
@@ -5084,6 +5111,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c->migrate = lxcapi_migrate;
c->console_log = lxcapi_console_log;
+ /* isulad add begin */
+ c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos;
+ /* isulad add end */
return c;
err:
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 9e06215..486531e 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -847,6 +847,16 @@ struct lxc_container {
* \return \c true if the container was rebooted successfully, else \c false.
*/
bool (*reboot2)(struct lxc_container *c, int timeout);
+
+ /*! isulad add
+ * \brief An API call to change the path of the console default fifos
+ *
+ * \param c Container.
+ * \param path Value of the console path.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out);
};
/*!
diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c
index 4060e7f..c507712 100644
--- a/src/lxc/terminal.c
+++ b/src/lxc/terminal.c
@@ -364,6 +364,20 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf,
return bytes_read;
}
+/* isulad: forward data to all fifos */
+static void lxc_forward_data_to_fifo(struct lxc_list *list, char *buf, int r)
+{
+ struct lxc_list *it,*next;
+ struct lxc_fifos_fd *elem = NULL;
+
+ lxc_list_for_each_safe(it, list, next) {
+ elem = it->elem;
+ lxc_write_nointr(elem->out_fd, buf, r);
+ }
+
+ return;
+}
+
int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
struct lxc_epoll_descr *descr)
{
@@ -384,7 +398,13 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
terminal->tty_state = NULL;
}
terminal->peer = -EBADF;
- } else {
+ close(fd);
+ return LXC_MAINLOOP_CONTINUE; /* isulad: do not close mainloop when peer close*/
+ } else if (lxc_terminal_is_fifo(fd, &terminal->fifos)) {
+ /* isulad: delete fifos when the client close */
+ lxc_terminal_delete_fifo(fd, &terminal->fifos);
+ return LXC_MAINLOOP_CONTINUE;
+ } else {
ERROR("Handler received unexpected file descriptor");
}
close(fd);
@@ -392,7 +412,7 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
return LXC_MAINLOOP_CLOSE;
}
- if (fd == terminal->peer)
+ if (fd == terminal->peer || lxc_terminal_is_fifo(fd, &terminal->fifos))
w = lxc_write_nointr(terminal->master, buf, r);
w_rbuf = w_log = 0;
@@ -401,6 +421,9 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
if (terminal->peer >= 0)
w = lxc_write_nointr(terminal->peer, buf, r);
+ /* isulad: forward data to fifos */
+ lxc_forward_data_to_fifo(&terminal->fifos, buf, r);
+
/* write to terminal ringbuffer */
if (terminal->buffer_size > 0)
w_rbuf = lxc_ringbuf_write(&terminal->ringbuf, buf, r);
@@ -450,6 +473,27 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
return 0;
}
+/* isulad add fifo to mainloop */
+static int lxc_console_mainloop_add_fifo(struct lxc_terminal *terminal)
+{
+ int ret = 0;
+ struct lxc_list *it,*next;
+ struct lxc_fifos_fd *elem = NULL;
+
+ lxc_list_for_each_safe(it, &terminal->fifos, next) {
+ elem = it->elem;
+ if (elem->in_fd >= 0) {
+ ret = lxc_mainloop_add_handler(terminal->descr, elem->in_fd,
+ lxc_terminal_io_cb, terminal);
+ if (ret) {
+ ERROR("console fifo %s not added to mainloop", elem->in_fifo);
+ return -1;
+ }
+ }
+ }
+ return ret;
+}
+
int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
struct lxc_terminal *terminal)
{
@@ -473,7 +517,20 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
*/
terminal->descr = descr;
- return lxc_terminal_mainloop_add_peer(terminal);
+ ret = lxc_terminal_mainloop_add_peer(terminal);
+ if (ret < 0) {
+ ERROR("Failed to add handler for terminal peer to mainloop");
+ return -1;
+ }
+
+ /* isulad add fifo to mainloop */
+ ret = lxc_console_mainloop_add_fifo(terminal);
+ if (ret < 0) {
+ ERROR("Failed to add handler for terminal fifos to mainloop");
+ return -1;
+ }
+
+ return 0;
}
int lxc_setup_tios(int fd, struct termios *oldtios)
@@ -812,6 +869,9 @@ void lxc_terminal_delete(struct lxc_terminal *terminal)
if (terminal->log_fd >= 0)
close(terminal->log_fd);
terminal->log_fd = -1;
+
+ /* isulad: delete all fifos */
+ lxc_terminal_delete_fifo(-1, &terminal->fifos);
}
/**
@@ -880,6 +940,77 @@ int lxc_terminal_create_log_file(struct lxc_terminal *terminal)
return 0;
}
+/* isulad: open terminal fifos */
+static int terminal_fifo_open(const char *fifo_path, int flags)
+{
+ int fd = -1;
+
+ fd = open(fifo_path, flags);
+ if (fd < 0) {
+ WARN("Failed to open fifo %s to send message: %s.", fifo_path,
+ strerror(errno));
+ return -1;
+ }
+
+ return fd;
+}
+
+/* isulad: set terminal fifos */
+static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, const char *out)
+{
+ int fifofd_in = -1, fifofd_out = -1;
+ struct lxc_fifos_fd *fifo_elem = NULL;
+
+ if (!in || !out)
+ return -1;
+
+ if (!fifo_exists(in) || !fifo_exists(out)) {
+ ERROR("File %s or %s does not refer to a FIFO", in, out);
+ return -1;
+ }
+
+ fifofd_in = terminal_fifo_open(in, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fifofd_in < 0) {
+ ERROR("Failed to open FIFO: %s", in);
+ return -1;
+ }
+
+ fifofd_out = terminal_fifo_open(out, O_WRONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fifofd_out < 0) {
+ ERROR("Failed to open FIFO: %s", out);
+ close(fifofd_in);
+ return -1;
+ }
+
+ fifo_elem = malloc(sizeof(*fifo_elem));
+ if (!fifo_elem) {
+ close(fifofd_in);
+ close(fifofd_out);
+ return -1;
+ }
+ memset(fifo_elem, 0, sizeof(*fifo_elem));
+
+ fifo_elem->in_fifo = strdup(in);
+ fifo_elem->out_fifo = strdup(out);
+ fifo_elem->in_fd = fifofd_in;
+ fifo_elem->out_fd = fifofd_out;
+ lxc_list_add_elem(&fifo_elem->node, fifo_elem);
+ lxc_list_add_tail(&console->fifos, &fifo_elem->node);
+
+ return fifofd_in;
+}
+
+/* isulad: add default fifos */
+static int lxc_terminal_fifo_default(struct lxc_terminal *terminal)
+{
+ if (!terminal->init_fifo[0] || !terminal->init_fifo[1]) {
+ ERROR("Invalid default terminal fifos");
+ return -1;
+ }
+
+ return lxc_terminal_set_fifo(terminal, terminal->init_fifo[0], terminal->init_fifo[1]);
+}
+
int lxc_terminal_create(struct lxc_terminal *terminal)
{
int ret;
@@ -902,6 +1033,13 @@ int lxc_terminal_create(struct lxc_terminal *terminal)
goto err;
}
+ /* isulad: make master NONBLOCK */
+ ret = fd_nonblock(terminal->master);
+ if (ret < 0) {
+ SYSERROR("Failed to set O_NONBLOCK flag on terminal master");
+ goto err;
+ }
+
ret = fd_cloexec(terminal->slave, true);
if (ret < 0) {
SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave");
@@ -914,6 +1052,13 @@ int lxc_terminal_create(struct lxc_terminal *terminal)
goto err;
}
+ /* isulad: open fifos */
+ ret = lxc_terminal_fifo_default(terminal);
+ if (ret < 0) {
+ ERROR("Failed to allocate fifo terminal");
+ goto err;
+ }
+
return 0;
err:
@@ -1198,12 +1343,55 @@ void lxc_terminal_init(struct lxc_terminal *terminal)
lxc_terminal_info_init(&terminal->proxy);
}
+/* isulad: judge the fd whether is fifo */
+static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list)
+{
+ struct lxc_list *it,*next;
+ struct lxc_fifos_fd *elem = NULL;
+
+ lxc_list_for_each_safe(it, list, next) {
+ elem = it->elem;
+ if (elem->in_fd == fd)
+ return true;
+ }
+
+ return false;
+}
+
+/* isulad: if fd == -1, means delete all the fifos*/
+int lxc_terminal_delete_fifo(int fd, struct lxc_list *list)
+{
+ struct lxc_list *it,*next;
+ struct lxc_fifos_fd *elem = NULL;
+
+ lxc_list_for_each_safe(it, list, next) {
+ elem = it->elem;
+ if (elem->in_fd == fd || -1 == fd) {
+ INFO("Delete fifo fd %d", fd);
+ lxc_list_del(it);
+ if (elem->in_fifo)
+ free(elem->in_fifo);
+ if (elem->out_fifo)
+ free(elem->out_fifo);
+ close(elem->in_fd);
+ close(elem->out_fd);
+ free(elem);
+ }
+ }
+
+ return 0;
+}
+
void lxc_terminal_conf_free(struct lxc_terminal *terminal)
{
free(terminal->log_path);
free(terminal->path);
if (terminal->buffer_size > 0 && terminal->ringbuf.addr)
lxc_ringbuf_release(&terminal->ringbuf);
+ /*isulad: free console fifos */
+ free(terminal->init_fifo[0]);
+ free(terminal->init_fifo[1]);
+ lxc_terminal_delete_fifo(-1, &terminal->fifos);
}
int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *terminal)
diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h
index bfd271f..d25da65 100644
--- a/src/lxc/terminal.h
+++ b/src/lxc/terminal.h
@@ -115,6 +115,17 @@ struct lxc_terminal {
/* the in-memory ringbuffer */
struct lxc_ringbuf ringbuf;
};
+ char *init_fifo[2]; /* isulad: default fifos for the start */
+ struct lxc_list fifos; /* isulad: fifos used to forward teminal */
+};
+
+/* isulad: fifo struct */
+struct lxc_fifos_fd {
+ char *in_fifo;
+ char *out_fifo;
+ int in_fd;
+ int out_fd;
+ struct lxc_list node;
};
/**
@@ -295,4 +306,9 @@ extern void lxc_terminal_init(struct lxc_terminal *terminal);
extern int lxc_terminal_map_ids(struct lxc_conf *c,
struct lxc_terminal *terminal);
+/* isulad: judge the fd whether is fifo*/
+static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list);
+/* isulad: if fd == -1, means delete all the fifos*/
+int lxc_terminal_delete_fifo(int fd, struct lxc_list *list);
+
#endif /* __LXC_TERMINAL_H */
diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h
index 810050a..b7af2b5 100644
--- a/src/lxc/tools/arguments.h
+++ b/src/lxc/tools/arguments.h
@@ -62,6 +62,7 @@ struct lxc_arguments {
/* for lxc-start */
const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */
+ const char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */
/* for lxc-console */
unsigned int ttynum;
@@ -172,6 +173,10 @@ struct lxc_arguments {
#define OPT_SHARE_IPC OPT_USAGE - 4
#define OPT_SHARE_UTS OPT_USAGE - 5
#define OPT_SHARE_PID OPT_USAGE - 6
+/* isulad add begin */
+#define OPT_INPUT_FIFO OPT_USAGE - 7
+#define OPT_OUTPUT_FIFO OPT_USAGE - 8
+/* isulad add end*/
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
char *const argv[]);
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 4553cb5..8f03f11 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -69,6 +69,8 @@ static const struct option my_longopts[] = {
{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
{"share-uts", required_argument, 0, OPT_SHARE_UTS},
{"share-pid", required_argument, 0, OPT_SHARE_PID},
+ {"in-fifo", required_argument, 0, OPT_INPUT_FIFO},
+ {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO},
LXC_COMMON_OPTIONS
};
@@ -140,6 +142,12 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
case OPT_SHARE_PID:
args->share_ns[LXC_NS_PID] = arg;
break;
+ case OPT_INPUT_FIFO:
+ args->terminal_fifos[0] = arg;
+ break;
+ case OPT_OUTPUT_FIFO:
+ args->terminal_fifos[1] = arg;
+ break;
}
return 0;
}
@@ -322,6 +330,9 @@ int main(int argc, char *argv[])
if (my_args.close_all_fds)
c->want_close_all_fds(c, true);
+ if (my_args.terminal_fifos[0] && my_args.terminal_fifos[1])
+ c->set_terminal_init_fifos(c, my_args.terminal_fifos[0], my_args.terminal_fifos[1]);
+
if (args == default_args)
err = c->start(c, 0, NULL) ? EXIT_SUCCESS : EXIT_FAILURE;
else
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 6e9165a..67c3b3e 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -611,6 +611,19 @@ bool dir_exists(const char *path)
return S_ISDIR(sb.st_mode);
}
+bool fifo_exists(const char *path)
+{
+ struct stat sb;
+ int ret;
+
+ ret = stat(path, &sb);
+ if (ret < 0)
+ // could be something other than eexist, just say no
+ return false;
+ return S_ISFIFO(sb.st_mode);
+}
+
+
/* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS.
* FNV has good anti collision properties and we're not worried
* about pre-image resistance or one-way-ness, we're just trying to make
@@ -1715,6 +1728,16 @@ int fd_cloexec(int fd, bool cloexec)
return 0;
}
+/* isulad: fd_nonblock */
+int fd_nonblock(int fd)
+{
+ long flags;
+
+ flags = fcntl(fd, F_GETFL);
+
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+}
+
int recursive_destroy(char *dirname)
{
int ret;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 94196d0..2d38178 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -147,6 +147,8 @@ extern gid_t get_ns_gid(gid_t orig);
extern bool dir_exists(const char *path);
+extern bool fifo_exists(const char *path);
+
#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
extern uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
@@ -242,4 +244,6 @@ extern int fd_cloexec(int fd, bool cloexec);
extern int recursive_destroy(char *dirname);
extern int lxc_setup_keyring(void);
+extern int fd_nonblock(int fd);
+
#endif /* __LXC_UTILS_H */
--
1.8.3.1