[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