[lxc rootfs mount point]
)], [], [with_rootfs_path=['${libdir}/lxc/rootfs']])
+# Container log path. By default, use $lxcpath.
+AC_MSG_CHECKING([Whether to place logfiles in container config path])
+AC_ARG_ENABLE([configpath-log],
+ [AC_HELP_STRING([--enable-configpath-log], [use logfiles in config path])],
+ [use_configpath_logs=yes], [use_configpath_logs=no])
+AC_MSG_RESULT([$use_configpath_logs])
+AM_CONDITIONAL([USE_CONFIGPATH_LOGS], [test "$use_configpath_logs" = "yes"])
+
+if test "$use_configpath_logs" = "yes"; then
+ default_log_path="${with_config_path}"
+else
+ default_log_path="/var/log/lxc"
+fi
+
+AC_ARG_WITH([log-path],
+ [AC_HELP_STRING(
+ [--with-log-path=dir],
+ [per container log path]
+ )], [], [with_log_path=['${default_log_path}']])
+
# Expand some useful variables
AS_AC_EXPAND(PREFIX, "$prefix")
AS_AC_EXPAND(LIBDIR, "$libdir")
AS_AC_EXPAND(LXCROOTFSMOUNT, "$with_rootfs_path")
AS_AC_EXPAND(LXCTEMPLATEDIR, "$datadir/lxc/templates")
AS_AC_EXPAND(LXCINITDIR, "$libexecdir")
+AS_AC_EXPAND(LOGPATH, "$with_log_path")
# Check for some standard kernel headers
AC_CHECK_HEADERS([linux/unistd.h linux/netlink.h linux/genetlink.h],
-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
-DLXCPATH=\"$(LXCPATH)\" \
-DLXCINITDIR=\"$(LXCINITDIR)\" \
- -DLXCTEMPLATEDIR=\"$(LXCTEMPLATEDIR)\"
+ -DLXCTEMPLATEDIR=\"$(LXCTEMPLATEDIR)\" \
+ -DLOGPATH=\"$(LOGPATH)\"
if ENABLE_APPARMOR
AM_CFLAGS += -DHAVE_APPARMOR
endif
+if USE_CONFIGPATH_LOGS
+AM_CFLAGS += -DUSE_CONFIGPATH_LOGS
+endif
+
if ENABLE_SECCOMP
AM_CFLAGS += -DHAVE_SECCOMP
liblxc_so_SOURCES += seccomp.c
static int config_logfile(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
- if (lxc_log_get_file()) {
- DEBUG("Log file already specified - ignoring new value");
- return 0;
- }
-
return lxc_log_set_file(value);
}
int lxc_log_fd = -1;
static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
static int lxc_loglevel_specified = 0;
+// if logfile was specifed on command line, it won't be overridden by lxc.logfile
+static int lxc_log_specified = 0;
lxc_log_define(lxc_log, lxc);
log_prefix[sizeof(log_prefix) - 1] = 0;
}
+static int build_dir(const char *name)
+{
+ char *n = strdup(name); // because we'll be modifying it
+ char *p, *e;
+ int ret;
+
+ if (!n) {
+ ERROR("Out of memory while creating directory '%s'.", name);
+ return -1;
+ }
+
+ e = &n[strlen(n)];
+ for (p = n+1; p < e; p++) {
+ if (*p != '/')
+ continue;
+ *p = '\0';
+ if (access(n, F_OK)) {
+ ret = lxc_unpriv(mkdir(n, 0755));
+ if (ret && errno != -EEXIST) {
+ SYSERROR("failed to create directory '%s'.", n);
+ free(n);
+ return -1;
+ }
+ }
+ *p = '/';
+ }
+ free(n);
+ return 0;
+}
+
/*---------------------------------------------------------------------------*/
static int log_open(const char *name)
{
return newfd;
}
+static char *build_log_path(const char *name)
+{
+ char *p;
+ int len, ret;
+
+ /*
+ * '$logpath' + '/' + '$name' + '.log' + '\0'
+ * or
+ * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
+ * sizeof(LOGPATH) includes its \0
+ */
+ len = sizeof(LOGPATH) + strlen(name) + 6;
+#if USE_CONFIGPATH_LOGS
+ len += strlen(name) + 1; /* add "/$container_name/" */
+#endif
+ p = malloc(len);
+ if (!p)
+ return p;
+#if USE_CONFIGPATH_LOGS
+ ret = snprintf(p, len, "%s/%s/%s.log", LOGPATH, name, name);
+#else
+ ret = snprintf(p, len, "%s/%s.log", LOGPATH, name);
+#endif
+ if (ret < 0 || ret >= len) {
+ free(p);
+ return NULL;
+ }
+ return p;
+}
+
+int do_lxc_log_set_file(const char *fname, int from_default);
+
/*---------------------------------------------------------------------------*/
-extern int lxc_log_init(const char *file, const char *priority,
- const char *prefix, int quiet)
+extern int lxc_log_init(const char *name, const char *file,
+ const char *priority, const char *prefix, int quiet)
{
int lxc_priority = LXC_LOG_PRIORITY_ERROR;
+ int ret;
+ char *tmpfile = NULL;
+ int want_lxc_log_specified = 0;
if (lxc_log_fd != -1)
return 0;
if (prefix)
lxc_log_setprefix(prefix);
- if (file)
- return lxc_log_set_file(file);
+ if (file && strcmp(file, "none") == 0) {
+ want_lxc_log_specified = 1;
+ return 0;
+ }
- return 0;
+ if (!file) {
+ tmpfile = build_log_path(name);
+ if (!tmpfile) {
+ ERROR("could not build log path");
+ return -1;
+ }
+ } else {
+ want_lxc_log_specified = 1;
+ }
+
+ ret = do_lxc_log_set_file(tmpfile ? tmpfile : file, !want_lxc_log_specified);
+
+ if (want_lxc_log_specified)
+ lxc_log_specified = 1;
+ /*
+ * If !want_lxc_log_specified, that is, if the user did not request
+ * this logpath, then ignore failures and continue logging to console
+ */
+ if (!want_lxc_log_specified && ret != 0) {
+ INFO("Ignoring failure to open default logfile.");
+ ret = 0;
+ }
+
+ if (tmpfile)
+ free(tmpfile);
+
+ return ret;
}
/*
}
char *log_fname; // default to NULL, set in lxc_log_set_file.
-
/*
- * 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 logfile if previously unset.
+ * This can be called:
+ * 1. when a program calls lxc_log_init with no logfile parameter (in which
+ * case the default is used). In this case lxc.logfile can override this.
+ * 2. when a program calls lxc_log_init with a logfile parameter. In this
+ * case we don't want lxc.logfile to override this.
+ * 3. When a lxc.logfile entry is found in config file.
*/
-extern int lxc_log_set_file(const char *fname)
+int do_lxc_log_set_file(const char *fname, int from_default)
{
+ if (lxc_log_specified) {
+ INFO("lxc.logfile overriden by command line");
+ return 0;
+ }
if (lxc_log_fd != -1) {
- // this should've been caught at config_logfile.
- ERROR("Race in setting logfile?");
+ // we are overriding the default.
+ close(lxc_log_fd);
+ free(log_fname);
+ }
+
+#if USE_CONFIGPATH_LOGS
+ // we don't build_dir for the default if the default is
+ // i.e. /var/lib/lxc/$container/$container.log
+ if (!from_default)
+#endif
+ if (build_dir(fname)) {
+ ERROR("failed to create dir for log file \"%s\" : %s", fname,
+ strerror(errno));
return -1;
}
lxc_log_fd = log_open(fname);
- if (lxc_log_fd == -1) {
- ERROR("failed to open log file %s\n", fname);
+ if (lxc_log_fd == -1)
return -1;
- }
log_fname = strdup(fname);
return 0;
}
+extern int lxc_log_set_file(const char *fname)
+{
+ return do_lxc_log_set_file(fname, 0);
+}
+
extern int lxc_log_get_level(void)
{
if (!lxc_loglevel_specified)
extern int lxc_log_fd;
-extern int lxc_log_init(const char *file, const char *priority,
- const char *prefix, int quiet);
+extern int lxc_log_init(const char *name, const char *file,
+ const char *priority, const char *prefix, int quiet);
extern void lxc_log_setprefix(const char *a_prefix);
extern int lxc_log_set_level(int level);
if (ret)
return ret;
- ret = lxc_log_init(my_args.log_file, my_args.log_priority,
+ ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet);
if (ret)
return ret;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
if (ret)
return ret;
- ret = lxc_log_init(my_args.log_file, my_args.log_priority,
+ ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet);
if (ret)
return ret;
if (err)
return -1;
- err = lxc_log_init(my_args.log_file, my_args.log_priority,
+ err = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet);
if (err)
return -1;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
if (ret)
return 1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return 1;
if (lxc_caps_init())
exit(err);
- if (lxc_log_init(NULL, 0, basename(argv[0]), quiet))
+ if (lxc_log_init(NULL, "none", 0, basename(argv[0]), quiet))
exit(err);
if (!argv[optind]) {
if (ret)
return ret;
- ret = lxc_log_init(my_args.log_file, my_args.log_priority,
+ ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet);
if (ret)
return ret;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
else
args = my_args.argv;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return err;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
- if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
return -1;
c->set_cgroup_item = lxcapi_set_cgroup_item;
/* we'll allow the caller to update these later */
- if (lxc_log_init(NULL, NULL, "lxc_container", 0)) {
+ if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0)) {
fprintf(stderr, "failed to open log\n");
goto err;
}