The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1871
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Closes #1870. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From d88f9a21938e4ae4b7fffbbf23e5516b0a7c92b6 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 22 Oct 2017 00:46:39 +0200 Subject: [PATCH 1/4] commands: add LXC_CMD_GET_CONSOLE_LOG Add infrastructure to query console ringbuffer. Closes #1870. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/commands.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/lxc/commands.h | 3 +++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/lxc/commands.c b/src/lxc/commands.c index 4d440ba78..75345869b 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -91,6 +91,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd) [LXC_CMD_GET_LXCPATH] = "get_lxcpath", [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client", [LXC_CMD_SET_CONFIG_ITEM] = "set_config_item", + [LXC_CMD_GET_CONSOLE_LOG] = "get_console_log", }; if (cmd >= LXC_CMD_MAX) @@ -153,14 +154,19 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) lxc_cmd_str(cmd->req.cmd)); return ret; } - if (rsp->datalen > LXC_CMD_DATA_MAX) { + if (rsp->datalen > LXC_CMD_DATA_MAX && cmd->req.cmd != LXC_CMD_GET_CONSOLE_LOG) { ERROR("Command %s response data %d too long.", lxc_cmd_str(cmd->req.cmd), rsp->datalen); errno = EFBIG; return -1; } - rsp->data = malloc(rsp->datalen); + if (cmd->req.cmd == LXC_CMD_GET_CONSOLE_LOG) { + rsp->data = malloc(rsp->datalen + 1); + ((char *)rsp->data)[rsp->datalen] = '\0'; + } else { + rsp->data = malloc(rsp->datalen); + } if (!rsp->data) { ERROR("Command %s was unable to allocate response buffer.", lxc_cmd_str(cmd->req.cmd)); @@ -986,6 +992,52 @@ static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req, return lxc_cmd_rsp_send(fd, &rsp); } +char *lxc_cmd_get_console_log(const char *name, const char *lxcpath, size_t *len) +{ + int ret, stopped; + struct lxc_cmd_rr cmd = { + .req = { .cmd = LXC_CMD_GET_CONSOLE_LOG, + .data = &len, + .datalen = 0, + }, + }; + + ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); + if (ret < 0) + return NULL; + + if (cmd.rsp.ret < 0) + return NULL; + + *len = cmd.rsp.datalen; + + return cmd.rsp.data; +} + +static int lxc_cmd_get_console_log_callback(int fd, struct lxc_cmd_req *req, + struct lxc_handler *handler) +{ + struct lxc_cmd_rsp rsp; + size_t len = *(size_t *)req->data; + struct lxc_ringbuf *buf = &handler->conf->console.ringbuf; + + rsp.ret = -ENODATA; + rsp.data = NULL; + rsp.datalen = 0; + + /* there's nothing to read */ + if (buf->r_off == buf->w_off) + return lxc_cmd_rsp_send(fd, &rsp); + + rsp.ret = 0; + rsp.data = lxc_ringbuf_get_read_addr(buf); + rsp.datalen = lxc_ringbuf_used(buf); + if (len > 0 && len <= rsp.datalen) + rsp.datalen = len; + lxc_ringbuf_move_read_addr(buf, rsp.datalen); + return lxc_cmd_rsp_send(fd, &rsp); +} + static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, struct lxc_handler *handler) { @@ -1004,6 +1056,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback, [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback, [LXC_CMD_SET_CONFIG_ITEM] = lxc_cmd_set_config_item_callback, + [LXC_CMD_GET_CONSOLE_LOG] = lxc_cmd_get_console_log_callback, }; if (req->cmd >= LXC_CMD_MAX) { @@ -1026,6 +1079,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, { int ret; struct lxc_cmd_req req; + void *reqdata = NULL; struct lxc_handler *handler = data; ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req)); @@ -1066,9 +1120,19 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, } if (req.datalen > 0) { - void *reqdata; + /* LXC_CMD_GET_CONSOLE_LOG needs to be able to allocate data + * that exceeds LXC_CMD_DATA_MAX: use malloc() for that. + */ + if (req.cmd == LXC_CMD_GET_CONSOLE_LOG) + reqdata = alloca(req.datalen); + else + reqdata = malloc(req.datalen); + if (!reqdata) { + ERROR("Failed to allocate memory for \"%s\" command", + lxc_cmd_str(req.cmd)); + goto out_close; + } - reqdata = alloca(req.datalen); ret = recv(fd, reqdata, req.datalen, 0); if (ret != req.datalen) { WARN("Failed to receive full command request. Ignoring " @@ -1088,6 +1152,9 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, } out: + if (req.cmd == LXC_CMD_GET_CONSOLE_LOG && reqdata) + free(reqdata); + return ret; out_close: lxc_cmd_fd_cleanup(fd, handler, descr); diff --git a/src/lxc/commands.h b/src/lxc/commands.h index cc5eec3c5..a8176b3e3 100644 --- a/src/lxc/commands.h +++ b/src/lxc/commands.h @@ -49,6 +49,7 @@ typedef enum { LXC_CMD_GET_LXCPATH, LXC_CMD_ADD_STATE_CLIENT, LXC_CMD_SET_CONFIG_ITEM, + LXC_CMD_GET_CONSOLE_LOG, LXC_CMD_MAX, } lxc_cmd_t; @@ -124,5 +125,7 @@ extern int lxc_try_cmd(const char *name, const char *lxcpath); extern int lxc_cmd_set_config_item(const char *name, const char *item, const char *value, const char *lxcpath); +extern char *lxc_cmd_get_console_log(const char *name, const char *lxcpath, + size_t *len); #endif /* __commands_h */ From d614c2e63980905a614546e780908c455c9642be Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 22 Oct 2017 00:47:28 +0200 Subject: [PATCH 2/4] commands: non-functional changes Closes #1870. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/commands.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/lxc/commands.c b/src/lxc/commands.c index 75345869b..8be1b8c84 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -997,8 +997,8 @@ char *lxc_cmd_get_console_log(const char *name, const char *lxcpath, size_t *len int ret, stopped; struct lxc_cmd_rr cmd = { .req = { .cmd = LXC_CMD_GET_CONSOLE_LOG, - .data = &len, - .datalen = 0, + .data = len, + .datalen = sizeof(size_t), }, }; @@ -1084,8 +1084,8 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req)); if (ret == -EACCES) { - /* we don't care for the peer, just send and close */ - struct lxc_cmd_rsp rsp = { .ret = ret }; + /* We don't care for the peer, just send and close. */ + struct lxc_cmd_rsp rsp = {.ret = ret}; lxc_cmd_rsp_send(fd, &rsp); goto out_close; @@ -1098,23 +1098,21 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, goto out_close; } - if (!ret) { + if (ret == 0) { DEBUG("Peer has disconnected for \"%s\"", lxc_cmd_str(req.cmd)); goto out_close; } if (ret != sizeof(req)) { WARN("Failed to receive full command request. Ignoring request " - "for \"%s\"", - lxc_cmd_str(req.cmd)); + "for \"%s\"", lxc_cmd_str(req.cmd)); ret = -1; goto out_close; } if (req.datalen > LXC_CMD_DATA_MAX) { ERROR("Received command data length %d is too large for " - "command \"%s\"", - req.datalen, lxc_cmd_str(req.cmd)); + "command \"%s\"", req.datalen, lxc_cmd_str(req.cmd)); ret = -1; goto out_close; } @@ -1124,9 +1122,9 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, * that exceeds LXC_CMD_DATA_MAX: use malloc() for that. */ if (req.cmd == LXC_CMD_GET_CONSOLE_LOG) - reqdata = alloca(req.datalen); - else reqdata = malloc(req.datalen); + else + reqdata = alloca(req.datalen); if (!reqdata) { ERROR("Failed to allocate memory for \"%s\" command", lxc_cmd_str(req.cmd)); @@ -1136,17 +1134,17 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, ret = recv(fd, reqdata, req.datalen, 0); if (ret != req.datalen) { WARN("Failed to receive full command request. Ignoring " - "request for \"%s\"", - lxc_cmd_str(req.cmd)); + "request for \"%s\"", lxc_cmd_str(req.cmd)); ret = -1; goto out_close; } + req.data = reqdata; } ret = lxc_cmd_process(fd, &req, handler); if (ret) { - /* this is not an error, but only a request to close fd */ + /* This is not an error, but only a request to close fd. */ ret = 0; goto out_close; } @@ -1156,6 +1154,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, free(reqdata); return ret; + out_close: lxc_cmd_fd_cleanup(fd, handler, descr); goto out; From 2f70fee4622f4c78c9e5fe14087cbe36d7b8183f Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 22 Oct 2017 00:48:02 +0200 Subject: [PATCH 3/4] lxccontainer: add console_get_log() Closes #1870. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/lxccontainer.c | 8 ++++++++ src/lxc/lxccontainer.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index efb1bf7ae..e56e0b421 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -516,6 +516,13 @@ static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd, return ret; } +static char *do_lxcapi_console_get_log(struct lxc_container *c, size_t *len) +{ + return lxc_cmd_get_console_log(c->name, do_lxcapi_get_config_path(c), len); +} + +WRAP_API_1(char *, lxcapi_console_get_log, size_t *) + static pid_t do_lxcapi_init_pid(struct lxc_container *c) { if (!c) @@ -4607,6 +4614,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath c->checkpoint = lxcapi_checkpoint; c->restore = lxcapi_restore; c->migrate = lxcapi_migrate; + c->console_get_log = lxcapi_console_get_log; return c; diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h index 84bdab81c..89a69088d 100644 --- a/src/lxc/lxccontainer.h +++ b/src/lxc/lxccontainer.h @@ -834,6 +834,8 @@ struct lxc_container { * \return \c true on success, else \c false. */ bool (*set_running_config_item)(struct lxc_container *c, const char *key, const char *value); + + char *(*console_get_log)(struct lxc_container *c, size_t *len); }; /*! From b282c8d9c0066f6f57bd2456838fb2247c23bce2 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 22 Oct 2017 00:48:28 +0200 Subject: [PATCH 4/4] [DO NOT MERGE - TESTING ONLY] tools: retrieve console log Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/arguments.h | 1 + src/lxc/tools/lxc_console.c | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h index b07caf42b..adc1cafbd 100644 --- a/src/lxc/arguments.h +++ b/src/lxc/arguments.h @@ -63,6 +63,7 @@ struct lxc_arguments { /* for lxc-console */ unsigned int ttynum; char escape; + bool show_log; /* for lxc-wait */ char *states; diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c index 66b909162..e2fa9b8ed 100644 --- a/src/lxc/tools/lxc_console.c +++ b/src/lxc/tools/lxc_console.c @@ -65,11 +65,15 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) case 'e': args->escape = etoc(arg); break; + case 's': + args->show_log = true; + break; } return 0; } static const struct option my_longopts[] = { + {"show-log", no_argument, 0, 's'}, {"tty", required_argument, 0, 't'}, {"escape", required_argument, 0, 'e'}, LXC_COMMON_OPTIONS @@ -86,17 +90,20 @@ Options :\n\ -n, --name=NAME NAME of the container\n\ -t, --tty=NUMBER console tty number\n\ -e, --escape=PREFIX prefix for escape command\n\ + -s, --show-log show console log\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .checker = NULL, .ttynum = -1, .escape = 1, + .show_log = false, }; int main(int argc, char *argv[]) { int ret; + char *ringbuf; struct lxc_container *c; struct lxc_log log; @@ -155,11 +162,19 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - ret = c->console(c, my_args.ttynum, 0, 1, 2, my_args.escape); - if (ret < 0) { + if (my_args.show_log) { + ringbuf = c->console_get_log(c, &(size_t){0}); lxc_container_put(c); - exit(EXIT_FAILURE); + if (!ringbuf) + exit(EXIT_FAILURE); + + printf("%s\n", ringbuf); + exit(EXIT_SUCCESS); } + ret = c->console(c, my_args.ttynum, 0, 1, 2, my_args.escape); lxc_container_put(c); + if (ret < 0) + exit(EXIT_FAILURE); + exit(EXIT_SUCCESS); }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel