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

Reply via email to