[lxc-devel] [PATCH RFC] log: introduce container logging
Serge Hallyn
serge.hallyn at ubuntu.com
Wed Mar 12 00:13:04 UTC 2014
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.
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
More information about the lxc-devel
mailing list