confile: add lxc.console.buffer.logfile

parent 28f3b1cd
...@@ -709,6 +709,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ...@@ -709,6 +709,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<varlistentry> <varlistentry>
<term> <term>
<option>lxc.console.buffer.logfile</option>
</term>
<listitem>
<para>
Setting this option instructs liblxc to write the in-memory
ringbuffer to disk. For performance reasons liblxc will only write
the in-memory ringbuffer to disk when requested. Note that the this
option is only used by liblxc when
<option>lxc.console.buffer.size</option> is set.
By default liblxc will dump the contents of the in-memory ringbuffer
to disk when the container terminates. This allows users to diagnose
boot failures when the container crashed before an API request to
retrieve the in-memory ringbuffer could be sent or handled.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.console.logfile</option> <option>lxc.console.logfile</option>
</term> </term>
<listitem> <listitem>
......
...@@ -1051,7 +1051,7 @@ static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req, ...@@ -1051,7 +1051,7 @@ static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
if (log->write_logfile && rsp.datalen > 0) { if (log->write_logfile && rsp.datalen > 0) {
rsp.ret = -ENOENT; rsp.ret = -ENOENT;
if (!console->log_path) if (!console->buffer_log_file)
goto out; goto out;
rsp.ret = lxc_console_write_ringbuffer(console); rsp.ret = lxc_console_write_ringbuffer(console);
......
...@@ -2430,9 +2430,11 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2430,9 +2430,11 @@ struct lxc_conf *lxc_conf_init(void)
new->loglevel = LXC_LOG_LEVEL_NOTSET; new->loglevel = LXC_LOG_LEVEL_NOTSET;
new->personality = -1; new->personality = -1;
new->autodev = 1; new->autodev = 1;
new->console.buffer_log_file = NULL;
new->console.buffer_log_file_fd = -1;
new->console.buffer_size = 0;
new->console.log_path = NULL; new->console.log_path = NULL;
new->console.log_fd = -1; new->console.log_fd = -1;
new->console.buffer_size = 0;
new->console.path = NULL; new->console.path = NULL;
new->console.peer = -1; new->console.peer = -1;
new->console.peerpty.busy = -1; new->console.peerpty.busy = -1;
...@@ -3461,6 +3463,7 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -3461,6 +3463,7 @@ void lxc_conf_free(struct lxc_conf *conf)
return; return;
if (current_config == conf) if (current_config == conf)
current_config = NULL; current_config = NULL;
free(conf->console.buffer_log_file);
free(conf->console.log_path); free(conf->console.log_path);
free(conf->console.path); free(conf->console.path);
if (conf->console.buffer_size > 0 && conf->console.ringbuf.addr) if (conf->console.buffer_size > 0 && conf->console.ringbuf.addr)
......
...@@ -153,7 +153,17 @@ struct lxc_console { ...@@ -153,7 +153,17 @@ struct lxc_console {
char name[MAXPATHLEN]; char name[MAXPATHLEN];
struct termios *tios; struct termios *tios;
struct lxc_tty_state *tty_state; struct lxc_tty_state *tty_state;
/* size of the ringbuffer */
uint64_t buffer_size; uint64_t buffer_size;
/* path to the log file for the ringbuffer */
char *buffer_log_file;
/* fd to the log file for the ringbuffer */
int buffer_log_file_fd;
/* the in-memory ringbuffer */
struct lxc_ringbuf ringbuf; struct lxc_ringbuf ringbuf;
}; };
......
...@@ -83,6 +83,7 @@ lxc_config_define(cap_keep); ...@@ -83,6 +83,7 @@ lxc_config_define(cap_keep);
lxc_config_define(cgroup_controller); lxc_config_define(cgroup_controller);
lxc_config_define(cgroup_dir); lxc_config_define(cgroup_dir);
lxc_config_define(console_logfile); lxc_config_define(console_logfile);
lxc_config_define(console_buffer_logfile);
lxc_config_define(console_buffer_size); lxc_config_define(console_buffer_size);
lxc_config_define(console_path); lxc_config_define(console_path);
lxc_config_define(environment); lxc_config_define(environment);
...@@ -149,6 +150,7 @@ static struct lxc_config_t config[] = { ...@@ -149,6 +150,7 @@ static struct lxc_config_t config[] = {
{ "lxc.cap.keep", false, set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, }, { "lxc.cap.keep", false, set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
{ "lxc.cgroup.dir", false, set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, }, { "lxc.cgroup.dir", false, set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, },
{ "lxc.cgroup", false, set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, }, { "lxc.cgroup", false, set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, },
{ "lxc.console.buffer.logfile", false, set_config_console_buffer_logfile, get_config_console_buffer_logfile, clr_config_console_buffer_logfile, },
{ "lxc.console.buffer.size", false, set_config_console_buffer_size, get_config_console_buffer_size, clr_config_console_buffer_size, }, { "lxc.console.buffer.size", false, set_config_console_buffer_size, get_config_console_buffer_size, clr_config_console_buffer_size, },
{ "lxc.console.logfile", false, set_config_console_logfile, get_config_console_logfile, clr_config_console_logfile, }, { "lxc.console.logfile", false, set_config_console_logfile, get_config_console_logfile, clr_config_console_logfile, },
{ "lxc.console.path", false, set_config_console_path, get_config_console_path, clr_config_console_path, }, { "lxc.console.path", false, set_config_console_path, get_config_console_path, clr_config_console_path, },
...@@ -1841,6 +1843,13 @@ static int set_config_console_buffer_size(const char *key, const char *value, ...@@ -1841,6 +1843,13 @@ static int set_config_console_buffer_size(const char *key, const char *value,
return 0; return 0;
} }
static int set_config_console_buffer_logfile(const char *key, const char *value,
struct lxc_conf *lxc_conf,
void *data)
{
return set_config_path_item(&lxc_conf->console.buffer_log_file, value);
}
int append_unexp_config_line(const char *line, struct lxc_conf *conf) int append_unexp_config_line(const char *line, struct lxc_conf *conf)
{ {
size_t len = conf->unexpanded_len, linelen = strlen(line); size_t len = conf->unexpanded_len, linelen = strlen(line);
...@@ -3098,6 +3107,13 @@ static int get_config_console_buffer_size(const char *key, char *retv, ...@@ -3098,6 +3107,13 @@ static int get_config_console_buffer_size(const char *key, char *retv,
return lxc_get_conf_uint64(c, retv, inlen, c->autodev); return lxc_get_conf_uint64(c, retv, inlen, c->autodev);
} }
static int get_config_console_buffer_logfile(const char *key, char *retv,
int inlen, struct lxc_conf *c,
void *data)
{
return lxc_get_conf_str(retv, inlen, c->console.buffer_log_file);
}
static int get_config_seccomp_profile(const char *key, char *retv, int inlen, static int get_config_seccomp_profile(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
...@@ -3509,6 +3525,15 @@ static inline int clr_config_console_buffer_size(const char *key, ...@@ -3509,6 +3525,15 @@ static inline int clr_config_console_buffer_size(const char *key,
return 0; return 0;
} }
static inline int clr_config_console_buffer_logfile(const char *key,
struct lxc_conf *c,
void *data)
{
free(c->console.buffer_log_file);
c->console.buffer_log_file = NULL;
return 0;
}
static inline int clr_config_seccomp_profile(const char *key, static inline int clr_config_seccomp_profile(const char *key,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
......
...@@ -558,19 +558,19 @@ int lxc_console_write_ringbuffer(struct lxc_console *console) ...@@ -558,19 +558,19 @@ int lxc_console_write_ringbuffer(struct lxc_console *console)
uint64_t used; uint64_t used;
struct lxc_ringbuf *buf = &console->ringbuf; struct lxc_ringbuf *buf = &console->ringbuf;
if (!console->log_path) if (!console->buffer_log_file)
return 0; return 0;
used = lxc_ringbuf_used(buf); used = lxc_ringbuf_used(buf);
if (used == 0) if (used == 0)
return 0; return 0;
fd = lxc_unpriv(open(console->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_TRUNC, 0600)); fd = lxc_unpriv(open(console->buffer_log_file, O_CLOEXEC | O_RDWR | O_CREAT | O_TRUNC, 0600));
if (fd < 0) { if (fd < 0) {
SYSERROR("Failed to open console log file \"%s\"", console->log_path); SYSERROR("Failed to open console log file \"%s\"", console->buffer_log_file);
return -EIO; return -EIO;
} }
DEBUG("Using \"%s\" as console log file", console->log_path); DEBUG("Using \"%s\" as console log file", console->buffer_log_file);
r_addr = lxc_ringbuf_get_read_addr(buf); r_addr = lxc_ringbuf_get_read_addr(buf);
ret = lxc_write_nointr(fd, r_addr, used); ret = lxc_write_nointr(fd, r_addr, used);
...@@ -698,7 +698,7 @@ int lxc_console_create(struct lxc_conf *conf) ...@@ -698,7 +698,7 @@ int lxc_console_create(struct lxc_conf *conf)
goto err; goto err;
} }
if (console->log_path && console->buffer_size <= 0) { if (console->log_path) {
console->log_fd = lxc_unpriv(open(console->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600)); console->log_fd = lxc_unpriv(open(console->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600));
if (console->log_fd < 0) { if (console->log_fd < 0) {
SYSERROR("Failed to open console log file \"%s\"", console->log_path); SYSERROR("Failed to open console log file \"%s\"", console->log_path);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment