[lxc-devel] [PATCH RFC] log: introduce container logging
S.Çağlar Onur
caglar at 10ur.org
Wed Mar 12 03:14:08 UTC 2014
Hi Serge,
On Tue, Mar 11, 2014 at 8:13 PM, Serge Hallyn <serge.hallyn at ubuntu.com> wrote:
> This is not intended to be applied yet.
>
> This patch adds real per-container, thread-safe log preferences. Currently
> if a program loads two containers which both set a lxc.logfile, and start
> then start them in sequence, the logfile for the second container will be
> used. This patch stores the log preferences in the lxc_container itself.
> It leaves ERROR/INFO/etc as global log print helpers, while the new
> CERROR/CINFO/etc become new per-container helpers. To demonstrate how to
> use these, some logging in lxcapi_start and lxcapi_create has been
> converted.
>
> What this patch ignores, and why I say this patch is not ready to be
> applied, is what to do about 'lxc-start -l info -o outfile'. With this
> patch, global logging (ERROR) will go to outfile, while per-container
> logging will not.
Wow, I didn't see that coming as I was thinking you were joking the
other day :) One possible solution to this global v.s per-container
logging problem could be using a well known global log file and
introducing a new argument to override it.
We could say that LXC_LOGPATH/lxc.log will have the global logs and
logfile parameter will have the per-container logs. I guess the
downside of this approach would be looking 2 different log files in 2
different locations in case of a failure.
Do you think we have lots of code that does something before we create
an lxc_container struct? I could be wrong but I suspect we don't have
much in as we almost have the lxc_container around all the time. So
maybe we can make everything per-container level.
> If we want the options provided to lxc-start to override what is in
> the container config file, perhaps lxc-start should simply call
> c->set_config_item("lxc.logfile", "outfile") right before lxc-start?
> Or should we say that the container configuration file values
> override command line values? (I don't think that makes a lot of sense
> as an end-user)
>
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
> ---
> src/lxc/confile.c | 15 ++---
> src/lxc/log.c | 145 ++++++++++++++++++++++++++++++++-----------------
> src/lxc/log.h | 117 ++++++++++++++++++++++++++++++---------
> src/lxc/lxccontainer.c | 93 ++++++++++++++++---------------
> src/lxc/lxccontainer.h | 7 +++
> 5 files changed, 246 insertions(+), 131 deletions(-)
>
> diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> index 8b1c0b6..9eeb90b 100644
> --- a/src/lxc/confile.c
> +++ b/src/lxc/confile.c
> @@ -1089,14 +1089,7 @@ static int config_lsm_se_context(const char *key, const char *value,
> static int config_logfile(const char *key, const char *value,
> struct lxc_conf *lxc_conf)
> {
> - int ret;
> -
> - // store these values in the lxc_conf, and then try to set for
> - // actual current logging.
> - ret = config_path_item(&lxc_conf->logfile, value);
> - if (ret == 0)
> - ret = lxc_log_set_file(lxc_conf->logfile);
> - return ret;
> + return config_path_item(&lxc_conf->logfile, value);
> }
>
> static int config_loglevel(const char *key, const char *value,
> @@ -1114,7 +1107,7 @@ static int config_loglevel(const char *key, const char *value,
> // store these values in the lxc_conf, and then try to set for
> // actual current logging.
> lxc_conf->loglevel = newlevel;
> - return lxc_log_set_level(newlevel);
> + return 0;
> }
>
> static int config_autodev(const char *key, const char *value,
> @@ -2089,9 +2082,9 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
> else if (strcmp(key, "lxc.se_context") == 0)
> v = c->lsm_se_context;
> else if (strcmp(key, "lxc.logfile") == 0)
> - v = lxc_log_get_file();
> + v = c->logfile;
> else if (strcmp(key, "lxc.loglevel") == 0)
> - v = lxc_log_priority_to_string(lxc_log_get_level());
> + v = lxc_log_priority_to_string(c->loglevel);
> else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
> return lxc_get_cgroup_entry(c, retv, inlen, "all");
> else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
> diff --git a/src/lxc/log.c b/src/lxc/log.c
> index d5b862e..a8ddc44 100644
> --- a/src/lxc/log.c
> +++ b/src/lxc/log.c
> @@ -40,16 +40,6 @@
> #define LXC_LOG_PREFIX_SIZE 32
> #define LXC_LOG_BUFFER_SIZE 512
>
> -#ifdef HAVE_TLS
> -__thread int lxc_log_fd = -1;
> -static __thread char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
> -static __thread char *log_fname = NULL;
> -/* command line values for logfile or logpriority should always override
> - * values from the configuration file or defaults
> - */
> -static __thread int lxc_logfile_specified = 0;
> -static __thread int lxc_loglevel_specified = 0;
> -#else
> int lxc_log_fd = -1;
> static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
> static char *log_fname = NULL;
> @@ -58,13 +48,12 @@ static char *log_fname = NULL;
> */
> static int lxc_logfile_specified = 0;
> static int lxc_loglevel_specified = 0;
> -#endif
>
> lxc_log_define(lxc_log, lxc);
>
> /*---------------------------------------------------------------------------*/
> static int log_append_stderr(const struct lxc_log_appender *appender,
> - struct lxc_log_event *event)
> + int log_fd, struct lxc_log_event *event)
> {
> if (event->priority < LXC_LOG_PRIORITY_ERROR)
> return 0;
> @@ -77,13 +66,15 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
>
> /*---------------------------------------------------------------------------*/
> static int log_append_logfile(const struct lxc_log_appender *appender,
> - struct lxc_log_event *event)
> + int log_fd, struct lxc_log_event *event)
> {
> char buffer[LXC_LOG_BUFFER_SIZE];
> int n;
> int ms;
>
> - if (lxc_log_fd == -1)
> + if (log_fd == -1)
> + log_fd = lxc_log_fd;
> + if (log_fd == -1)
> return 0;
>
> ms = event->timestamp.tv_usec / 1000;
> @@ -106,7 +97,7 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
>
> buffer[n] = '\n';
>
> - return write(lxc_log_fd, buffer, n + 1);
> + return write(log_fd, buffer, n + 1);
> }
>
> static struct lxc_log_appender log_appender_stderr = {
> @@ -121,18 +112,26 @@ static struct lxc_log_appender log_appender_logfile = {
> .next = NULL,
> };
>
> +static struct lxc_log_appender c_log_appender_logfile = {
> + .name = "logfile",
> + .append = log_append_logfile,
> + .next = NULL,
> +};
> +
> static struct lxc_log_category log_root = {
> .name = "root",
> .priority = LXC_LOG_PRIORITY_ERROR,
> .appender = NULL,
> .parent = NULL,
> + .log_fd = -1,
> };
>
> struct lxc_log_category lxc_log_category_lxc = {
> .name = "lxc",
> .priority = LXC_LOG_PRIORITY_ERROR,
> .appender = &log_appender_stderr,
> - .parent = &log_root
> + .parent = &log_root,
> + .log_fd = -1,
> };
>
> /*---------------------------------------------------------------------------*/
> @@ -368,6 +367,86 @@ extern int lxc_log_init(const char *name, const char *file,
> return ret;
> }
>
> +extern const char *lxc_log_get_file(void)
> +{
> + return log_fname;
> +}
> +
> +#include <lxccontainer.h>
> +
> +extern void container_log_close(struct lxc_container *c)
> +{
> + if (c->log_category) {
> + if (c->log_category->log_fd != -1)
> + close(c->log_category->log_fd);
> + free(c->log_category);
> + c->log_category = NULL;
> + }
> + free(c->log_file);
> +}
> +
> +static bool logfile_unchanged(struct lxc_container *c, int lvl)
> +{
> + int oldlvl = LXC_LOG_PRIORITY_NOTSET;
> +
> + if (c->log_category)
> + oldlvl = c->log_category->priority;
> + if (oldlvl != lvl)
> + return false;
> + if (!c->log_file && !c->lxc_conf->logfile)
> + return true;
> + if (!c->log_file || !c->lxc_conf->logfile)
> + return true;
> + return (strcmp(c->log_file, c->lxc_conf->logfile) == 0);
> +}
> +
> +extern bool container_log_init(struct lxc_container *c)
> +{
> + int lvl = c->lxc_conf->loglevel;
> + struct lxc_log_category *category;
> + const char *file = c->lxc_conf->logfile;
> +
> + if (logfile_unchanged(c, lvl))
> + return true;
> +
> + container_log_close(c);
> +
> + if (file) {
> + c->log_file = strdup(file);
> + if (!c->log_file) {
> + ERROR("%s: out of memory", __func__);
> + return false;
> + }
> + }
> +
> + category = malloc(sizeof(*category));
> + if (!category) {
> + ERROR("%s: out of memory", __func__);
> + return false;
> + }
> +
> + category->appender = &c_log_appender_logfile;
> + category->name = "container",
> + category->priority = lvl;
> + category->parent = NULL;
> + c->log_category = category;
> +
> + if (!file || strcmp(file, "none") == 0)
> + return true;
> +
> + if (build_dir(file)) {
> + ERROR("failed to create dir for log file \"%s\" : %s", file,
> + strerror(errno));
> + return false;
> + }
> +
> + c->log_category->log_fd = log_open(file);
> + if (c->log_category->log_fd == -1)
> + return false;
> +
> + return true;
> +}
> +
> extern void lxc_log_close(void)
> {
> if (lxc_log_fd == -1)
> @@ -378,23 +457,6 @@ extern void lxc_log_close(void)
> log_fname = NULL;
> }
>
> -/*
> - * This is called when we read a lxc.loglevel entry in a lxc.conf file. This
> - * happens after processing command line arguments, which override the .conf
> - * settings. So only set the level if previously unset.
> - */
> -extern int lxc_log_set_level(int level)
> -{
> - if (lxc_loglevel_specified)
> - return 0;
> - if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) {
> - ERROR("invalid log priority %d", level);
> - return -1;
> - }
> - lxc_log_category_lxc.priority = level;
> - return 0;
> -}
> -
> extern int lxc_log_get_level(void)
> {
> return lxc_log_category_lxc.priority;
> @@ -408,23 +470,6 @@ extern bool lxc_log_has_valid_level(void)
> return true;
> }
>
> -/*
> - * This is called when we read a lxc.logfile entry in a lxc.conf file. This
> - * happens after processing command line arguments, which override the .conf
> - * settings. So only set the file if previously unset.
> - */
> -extern int lxc_log_set_file(const char *fname)
> -{
> - if (lxc_logfile_specified)
> - return 0;
> - return __lxc_log_set_file(fname, 0);
> -}
> -
> -extern const char *lxc_log_get_file(void)
> -{
> - return log_fname;
> -}
> -
> extern void lxc_log_set_prefix(const char *prefix)
> {
> strncpy(log_prefix, prefix, sizeof(log_prefix));
> diff --git a/src/lxc/log.h b/src/lxc/log.h
> index 5252869..9097ffa 100644
> --- a/src/lxc/log.h
> +++ b/src/lxc/log.h
> @@ -25,6 +25,8 @@
> #define _log_h
>
> #include "config.h"
> +#include <lxccontainer.h>
> +#include "conf.h"
>
> #include <stdarg.h>
> #include <stdio.h>
> @@ -81,7 +83,7 @@ struct lxc_log_event {
> /* log appender object */
> struct lxc_log_appender {
> const char* name;
> - int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
> + int (*append)(const struct lxc_log_appender *, int log_fd, struct lxc_log_event *);
>
> /*
> * appenders can be stacked
> @@ -95,6 +97,11 @@ struct lxc_log_category {
> int priority;
> struct lxc_log_appender *appender;
> const struct lxc_log_category *parent;
> + /*
> + * if this is a container log_category, store log_fd here
> + * else use lxc_log_fd
> + */
> + int log_fd;
> };
>
> /*
> @@ -102,9 +109,11 @@ struct lxc_log_category {
> * given priority.
> */
> static inline int
> -lxc_log_priority_is_enabled(const struct lxc_log_category* category,
> - int priority)
> +lxc_log_priority_is_enabled(struct lxc_container *c,
> + const struct lxc_log_category* category, int priority)
> {
> + if (c && c->log_category)
> + category = c->log_category;
> while (category->priority == LXC_LOG_PRIORITY_NOTSET &&
> category->parent)
> category = category->parent;
> @@ -150,7 +159,7 @@ static inline int lxc_log_priority_to_int(const char* name)
> }
>
> static inline void
> -__lxc_log_append(const struct lxc_log_appender *appender,
> +__lxc_log_append(const struct lxc_log_appender *appender, int fd,
> struct lxc_log_event* event)
> {
> va_list va, *va_keep;
> @@ -159,18 +168,21 @@ __lxc_log_append(const struct lxc_log_appender *appender,
> while (appender) {
> va_copy(va, *va_keep);
> event->vap = &va;
> - appender->append(appender, event);
> + appender->append(appender, fd, event);
> appender = appender->next;
> va_end(va);
> }
> }
>
> static inline void
> -__lxc_log(const struct lxc_log_category* category,
> - struct lxc_log_event* event)
> +__lxc_log(struct lxc_container *c,
> + const struct lxc_log_category* category,
> + struct lxc_log_event* event)
> {
> + if (c && c->log_category)
> + category = c->log_category;
> while (category) {
> - __lxc_log_append(category->appender, event);
> + __lxc_log_append(category->appender, category->log_fd, event);
> category = category->parent;
> }
> }
> @@ -180,13 +192,15 @@ __lxc_log(const struct lxc_log_category* category,
> */
> #define lxc_log_priority_define(acategory, PRIORITY) \
> \
> -static inline void LXC_##PRIORITY(struct lxc_log_locinfo *, \
> - const char *, ...) __attribute__ ((format (printf, 2, 3))); \
> +static inline void LXC_##PRIORITY(struct lxc_container *c, \
> + struct lxc_log_locinfo *, const char *, ...) \
> + __attribute__ ((format (printf, 3, 4))); \
> \
> -static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
> +static inline void LXC_##PRIORITY(struct lxc_container *c, \
> + struct lxc_log_locinfo* locinfo, \
> const char* format, ...) \
> { \
> - if (lxc_log_priority_is_enabled(acategory, \
> + if (lxc_log_priority_is_enabled(c, acategory, \
> LXC_LOG_PRIORITY_##PRIORITY)) { \
> struct lxc_log_event evt = { \
> .category = (acategory)->name, \
> @@ -200,7 +214,7 @@ static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
> \
> va_start(va_ref, format); \
> evt.vap = &va_ref; \
> - __lxc_log(acategory, &evt); \
> + __lxc_log(c, acategory, &evt); \
> va_end(va_ref); \
> } \
> }
> @@ -238,47 +252,47 @@ static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
> */
> #define TRACE(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \
> + LXC_TRACE(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define DEBUG(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \
> + LXC_DEBUG(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define INFO(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_INFO(&locinfo, format, ##__VA_ARGS__); \
> + LXC_INFO(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define NOTICE(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \
> + LXC_NOTICE(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define WARN(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_WARN(&locinfo, format, ##__VA_ARGS__); \
> + LXC_WARN(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define ERROR(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \
> + LXC_ERROR(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define CRIT(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \
> + LXC_CRIT(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define ALERT(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \
> + LXC_ALERT(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
> #define FATAL(format, ...) do { \
> struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> - LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \
> + LXC_FATAL(NULL, &locinfo, format, ##__VA_ARGS__); \
> } while (0)
>
>
> @@ -287,11 +301,60 @@ static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
> ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \
> } while (0)
>
> -#ifdef HAVE_TLS
> -extern __thread int lxc_log_fd;
> -#else
> +
> +/* container logging versions */
> +#define CTRACE(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_TRACE(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CDEBUG(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_DEBUG(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CINFO(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_INFO(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CNOTICE(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_NOTICE(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CWARN(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_WARN(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CERROR(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_ERROR(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CCRIT(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_CRIT(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CALERT(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_ALERT(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +#define CFATAL(c, format, ...) do { \
> + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
> + LXC_FATAL(c, &locinfo, format, ##__VA_ARGS__); \
> +} while (0)
> +
> +
> +
> +#define CSYSERROR(c, format, ...) do { \
> + CERROR(c, "%s - " format, strerror(errno), ##__VA_ARGS__); \
> +} while (0)
> +
> extern int lxc_log_fd;
> -#endif
>
> extern int lxc_log_init(const char *name, const char *file,
> const char *priority, const char *prefix, int quiet,
> @@ -305,4 +368,6 @@ extern int lxc_log_get_level(void);
> extern bool lxc_log_has_valid_level(void);
> extern const char *lxc_log_get_prefix(void);
> extern void lxc_log_options_no_override();
> +extern bool container_log_init(struct lxc_container *c);
> +extern void container_log_close(struct lxc_container *c);
> #endif
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index c90b564..3d35bb0 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -250,6 +250,8 @@ static void lxc_container_free(struct lxc_container *c)
> c->config_path = NULL;
> }
>
> + container_log_close(c);
> +
> free(c);
> }
>
> @@ -415,11 +417,16 @@ static pid_t lxcapi_init_pid(struct lxc_container *c)
>
> static bool load_config_locked(struct lxc_container *c, const char *fname)
> {
> + bool bret = false;
> if (!c->lxc_conf)
> c->lxc_conf = lxc_conf_init();
> if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf))
> - return true;
> - return false;
> + bret = true;
> + /* If the logfile/level have been set, we need to update those */
> + if (!container_log_init(c))
> + ERROR("Failed to set the requested log settings");
> +
> + return bret;
> }
>
> static bool lxcapi_load_config(struct lxc_container *c, const char *alt_file)
> @@ -464,7 +471,7 @@ static bool lxcapi_want_daemonize(struct lxc_container *c, bool state)
> if (!c || !c->lxc_conf)
> return false;
> if (container_mem_lock(c)) {
> - ERROR("Error getting mem lock");
> + CERROR(c, "Error getting mem lock");
> return false;
> }
> c->daemonize = state;
> @@ -480,7 +487,7 @@ static bool lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
> if (!c || !c->lxc_conf)
> return false;
> if (container_mem_lock(c)) {
> - ERROR("Error getting mem lock");
> + CERROR(c, "Error getting mem lock");
> return false;
> }
> c->lxc_conf->close_all_fds = state;
> @@ -511,11 +518,11 @@ static bool wait_on_daemonized_start(struct lxc_container *c, int pid)
> */
> ret = waitpid(pid, &status, 0);
> if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
> - DEBUG("failed waiting for first dual-fork child");
> + CDEBUG(c, "failed waiting for first dual-fork child");
> return lxcapi_wait(c, "RUNNING", timeout);
> }
>
> -static bool am_single_threaded(void)
> +static bool am_single_threaded(struct lxc_container *c)
> {
> struct dirent dirent, *direntp;
> DIR *dir;
> @@ -523,7 +530,7 @@ static bool am_single_threaded(void)
>
> dir = opendir("/proc/self/task");
> if (!dir) {
> - INFO("failed to open /proc/self/task");
> + CINFO(c, "failed to open /proc/self/task");
> return false;
> }
>
> @@ -566,15 +573,15 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
> return false;
>
> if ((ret = ongoing_create(c)) < 0) {
> - ERROR("Error checking for incomplete creation");
> + CERROR(c, "Error checking for incomplete creation");
> return false;
> }
> if (ret == 2) {
> - ERROR("Error: %s creation was not completed", c->name);
> + CERROR(c, "Error: %s creation was not completed", c->name);
> c->destroy(c);
> return false;
> } else if (ret == 1) {
> - ERROR("Error: creation of %s is ongoing", c->name);
> + CERROR(c, "Error: creation of %s is ongoing", c->name);
> return false;
> }
>
> @@ -620,14 +627,14 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
> /* second fork to be reparented by init */
> pid = fork();
> if (pid < 0) {
> - SYSERROR("Error doing dual-fork");
> + CSYSERROR(c, "Error doing dual-fork");
> return false;
> }
> if (pid != 0)
> exit(0);
> /* like daemon(), chdir to / and redirect 0,1,2 to /dev/null */
> if (chdir("/")) {
> - SYSERROR("Error chdir()ing to /.");
> + CSYSERROR(c, "Error chdir()ing to /.");
> return false;
> }
> close(0);
> @@ -638,7 +645,7 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
> open("/dev/null", O_RDWR);
> setsid();
> } else {
> - if (!am_single_threaded()) {
> + if (!am_single_threaded(c)) {
> ERROR("Cannot start non-daemonized container when threaded");
> return false;
> }
> @@ -650,13 +657,13 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
> if (c->pidfile) {
> pid_fp = fopen(c->pidfile, "w");
> if (pid_fp == NULL) {
> - SYSERROR("Failed to create pidfile '%s' for '%s'",
> + CSYSERROR(c, "Failed to create pidfile '%s' for '%s'",
> c->pidfile, c->name);
> return false;
> }
>
> if (fprintf(pid_fp, "%d\n", getpid()) < 0) {
> - SYSERROR("Failed to write '%s'", c->pidfile);
> + CSYSERROR(c, "Failed to write '%s'", c->pidfile);
> fclose(pid_fp);
> pid_fp = NULL;
> return false;
> @@ -671,7 +678,7 @@ reboot:
> ret = lxc_start(c->name, argv, conf, c->config_path);
>
> if (conf->reboot) {
> - INFO("container requested reboot");
> + CINFO(c, "container requested reboot");
> conf->reboot = 0;
> goto reboot;
> }
> @@ -706,7 +713,7 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
> va_end(ap);
>
> if (!inargs) {
> - ERROR("Memory allocation error.");
> + CERROR(c, "Memory allocation error.");
> goto out;
> }
>
> @@ -758,7 +765,7 @@ static bool create_container_dir(struct lxc_container *c)
> if (errno == EEXIST)
> ret = 0;
> else
> - SYSERROR("failed to create container path for %s", c->name);
> + CSYSERROR(c, "failed to create container path for %s", c->name);
> }
> free(s);
> return ret == 0;
> @@ -796,7 +803,7 @@ static struct bdev *do_bdev_create(struct lxc_container *c, const char *type,
>
> bdev = bdev_create(dest, type, c->name, specs);
> if (!bdev) {
> - ERROR("Failed to create backing store type %s", type);
> + CERROR(c, "Failed to create backing store type %s", type);
> return NULL;
> }
>
> @@ -807,7 +814,7 @@ static struct bdev *do_bdev_create(struct lxc_container *c, const char *type,
>
> if (geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) {
> if (chown_mapped_root(bdev->dest, c->lxc_conf) < 0) {
> - ERROR("Error chowning %s to container root", bdev->dest);
> + CERROR(c, "Error chowning %s to container root", bdev->dest);
> bdev_put(bdev);
> return NULL;
> }
> @@ -868,7 +875,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
>
> pid = fork();
> if (pid < 0) {
> - SYSERROR("failed to fork task for container creation template");
> + CSYSERROR(c, "failed to fork task for container creation template");
> return false;
> }
>
> @@ -902,29 +909,29 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
>
> bdev = bdev_init(src, c->lxc_conf->rootfs.mount, NULL);
> if (!bdev) {
> - ERROR("Error opening rootfs");
> + CERROR(c, "Error opening rootfs");
> exit(1);
> }
>
> if (geteuid() == 0) {
> if (unshare(CLONE_NEWNS) < 0) {
> - ERROR("error unsharing mounts");
> + CERROR(c, "error unsharing mounts");
> exit(1);
> }
> if (detect_shared_rootfs()) {
> if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
> - SYSERROR("Failed to make / rslave to run template");
> - ERROR("Continuing...");
> + CSYSERROR(c, "Failed to make / rslave to run template");
> + CERROR(c, "Continuing...");
> }
> }
> }
> if (strcmp(bdev->type, "dir") != 0) {
> if (geteuid() != 0) {
> - ERROR("non-root users can only create directory-backed containers");
> + CERROR(c, "non-root users can only create directory-backed containers");
> exit(1);
> }
> if (bdev->ops->mount(bdev) < 0) {
> - ERROR("Error mounting rootfs");
> + CERROR(c, "Error mounting rootfs");
> exit(1);
> }
> } else { // TODO come up with a better way here!
> @@ -1000,7 +1007,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> struct id_map *map;
>
> if (!n2) {
> - SYSERROR("out of memory");
> + CSYSERROR(c, "out of memory");
> exit(1);
> }
> newargv[0] = tpath;
> @@ -1031,18 +1038,18 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> hostid_mapped = find_unmapped_nsuid(conf, ID_TYPE_UID);
> n2[n2args++] = "-m";
> if (hostid_mapped < 0) {
> - ERROR("Could not find free uid to map");
> + CERROR(c, "Could not find free uid to map");
> exit(1);
> }
> n2[n2args++] = malloc(200);
> if (!n2[n2args-1]) {
> - SYSERROR("out of memory");
> + CSYSERROR(c, "out of memory");
> exit(1);
> }
> ret = snprintf(n2[n2args-1], 200, "u:%d:%d:1",
> hostid_mapped, geteuid());
> if (ret < 0 || ret >= 200) {
> - ERROR("string too long");
> + CERROR(c, "string too long");
> exit(1);
> }
> }
> @@ -1055,18 +1062,18 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> hostgid_mapped = find_unmapped_nsuid(conf, ID_TYPE_GID);
> n2[n2args++] = "-m";
> if (hostgid_mapped < 0) {
> - ERROR("Could not find free uid to map");
> + CERROR(c, "Could not find free uid to map");
> exit(1);
> }
> n2[n2args++] = malloc(200);
> if (!n2[n2args-1]) {
> - SYSERROR("out of memory");
> + CSYSERROR(c, "out of memory");
> exit(1);
> }
> ret = snprintf(n2[n2args-1], 200, "g:%d:%d:1",
> hostgid_mapped, getegid());
> if (ret < 0 || ret >= 200) {
> - ERROR("string too long");
> + CERROR(c, "string too long");
> exit(1);
> }
> }
> @@ -1079,7 +1086,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> n2args += 4;
> n2 = realloc(n2, n2args * sizeof(char *));
> if (!n2) {
> - SYSERROR("out of memory");
> + CSYSERROR(c, "out of memory");
> exit(1);
> }
> // note n2[n2args-1] is NULL
> @@ -1095,12 +1102,12 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> }
> /* execute */
> execvp(tpath, newargv);
> - SYSERROR("failed to execute template %s", tpath);
> + CSYSERROR(c, "failed to execute template %s", tpath);
> exit(1);
> }
>
> if (wait_for_pid(pid) != 0) {
> - ERROR("container creation template for %s failed", c->name);
> + CERROR(c, "container creation template for %s failed", c->name);
> return false;
> }
>
> @@ -2046,6 +2053,7 @@ out:
> static bool set_config_item_locked(struct lxc_container *c, const char *key, const char *v)
> {
> struct lxc_config_t *config;
> + bool bret;
>
> if (!c->lxc_conf)
> c->lxc_conf = lxc_conf_init();
> @@ -2054,7 +2062,10 @@ static bool set_config_item_locked(struct lxc_container *c, const char *key, con
> config = lxc_getconfig(key);
> if (!config)
> return false;
> - return (0 == config->cb(key, v, c->lxc_conf));
> + bret = (0 == config->cb(key, v, c->lxc_conf));
> + if (!container_log_init(c))
> + ERROR("Failed to set the requested log settings");
> + return bret;
> }
>
> static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v)
> @@ -3384,12 +3395,6 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
> c->add_device_node = lxcapi_add_device_node;
> c->remove_device_node = lxcapi_remove_device_node;
>
> - /* we'll allow the caller to update these later */
> - if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
> - fprintf(stderr, "failed to open log\n");
> - goto err;
> - }
> -
> return c;
>
> err:
> diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
> index ba15ab7..a4982f8 100644
> --- a/src/lxc/lxccontainer.h
> +++ b/src/lxc/lxccontainer.h
> @@ -740,6 +740,13 @@ struct lxc_container {
> * \return \c true on success, else \c false.
> */
> bool (*remove_device_node)(struct lxc_container *c, const char *src_path, const char *dest_path);
> +
> + /*
> + * per-container log info
> + * If this is unset, then global logging is used
> + */
> + char *log_file;
> + struct lxc_log_category *log_category;
> };
>
> /*!
> --
> 1.9.0
>
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
--
S.Çağlar Onur <caglar at 10ur.org>
More information about the lxc-devel
mailing list