[lxc-devel] [lxc/master] RFC: API: add console ringbuffer extension
brauner on Github
lxc-bot at linuxcontainers.org
Sun Oct 22 07:59:43 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 381 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171022/565d8fdc/attachment.bin>
-------------- next part --------------
From d88f9a21938e4ae4b7fffbbf23e5516b0a7c92b6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at 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.brauner at 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.brauner at 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.brauner at 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.brauner at 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.brauner at 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.brauner at 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.brauner at 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);
}
More information about the lxc-devel
mailing list