]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/log.c
Add a new logger: syslog and Print the VM name in the logs
[mirror_lxc.git] / src / lxc / log.c
CommitLineData
e0b4037d
DL
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Cedric Le Goater <legoater@free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e0b4037d 22 */
3f53c691 23#include <assert.h>
0ad19a3f 24#include <stdio.h>
25#include <errno.h>
cb8c5720
CLG
26#include <limits.h>
27#include <unistd.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <string.h>
858377e4 31#include <pthread.h>
02d25a9e 32#include <time.h>
cb8c5720
CLG
33
34#define __USE_GNU /* for *_CLOEXEC */
35
64c57ea1
BD
36#include <syslog.h>
37#include <stdio.h>
38
cb8c5720
CLG
39#include <fcntl.h>
40#include <stdlib.h>
41
28f602ff
DL
42#include "log.h"
43#include "caps.h"
ab1bf971 44#include "utils.h"
cb8c5720 45
02d25a9e 46#define LXC_LOG_DATEFOMAT_SIZE 15
6b9f3917 47
9f4f402a 48int lxc_log_fd = -1;
64c57ea1 49static int syslog_enable = 0;
858377e4
SH
50int lxc_quiet_specified;
51int lxc_log_use_global_fd;
52static int lxc_loglevel_specified;
53
6b9f3917 54static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
ab1bf971 55static char *log_fname = NULL;
64c57ea1 56static char *log_vmname = NULL;
cb8c5720
CLG
57
58lxc_log_define(lxc_log, lxc);
59
64c57ea1
BD
60static int lxc_log_priority_to_syslog(int priority)
61{
62 switch (priority) {
63 case LXC_LOG_PRIORITY_FATAL:
64 return LOG_EMERG;
65 case LXC_LOG_PRIORITY_ALERT:
66 return LOG_ALERT;
67 case LXC_LOG_PRIORITY_CRIT:
68 return LOG_CRIT;
69 case LXC_LOG_PRIORITY_ERROR:
70 return LOG_ERR;
71 case LXC_LOG_PRIORITY_WARN:
72 return LOG_WARNING;
73 case LXC_LOG_PRIORITY_NOTICE:
74 case LXC_LOG_PRIORITY_NOTSET:
75 return LOG_NOTICE;
76 case LXC_LOG_PRIORITY_INFO:
77 return LOG_INFO;
78 case LXC_LOG_PRIORITY_TRACE:
79 case LXC_LOG_PRIORITY_DEBUG:
80 return LOG_DEBUG;
81 }
82
83 /* Not reached */
84 return LOG_NOTICE;
85}
86
87/*---------------------------------------------------------------------------*/
88static int log_append_syslog(const struct lxc_log_appender *appender,
89 struct lxc_log_event *event)
90{
91 char *msg;
92 int rc, len;
93 va_list args;
94
95 if (!syslog_enable)
96 return 0;
97
98 va_copy(args, *event->vap);
99 len = vsnprintf(NULL, 0, event->fmt, args) + 1;
100 va_end(args);
101 msg = malloc(len * sizeof(char));
102 if (msg == NULL)
103 return 0;
104 rc = vsnprintf(msg, len, event->fmt, *event->vap);
105 if (rc == -1 || rc >= len) {
106 free(msg);
107 return 0;
108 }
109
110 syslog(lxc_log_priority_to_syslog(event->priority),
111 "%s %s - %s:%s:%d - %s" ,
112 log_vmname ? log_vmname : "",
113 event->category,
114 event->locinfo->file, event->locinfo->func,
115 event->locinfo->line,
116 msg);
117 free(msg);
118 return 0;
119}
120
d737c074
MN
121/*---------------------------------------------------------------------------*/
122static int log_append_stderr(const struct lxc_log_appender *appender,
123 struct lxc_log_event *event)
124{
125 if (event->priority < LXC_LOG_PRIORITY_ERROR)
126 return 0;
127
64c57ea1 128 fprintf(stderr, "%s: %s", log_prefix, log_vmname ? log_vmname : "");
15bc516e 129 fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
d737c074
MN
130 vfprintf(stderr, event->fmt, *event->vap);
131 fprintf(stderr, "\n");
132 return 0;
133}
134
cb8c5720
CLG
135/*---------------------------------------------------------------------------*/
136static int log_append_logfile(const struct lxc_log_appender *appender,
5fd8380b 137 struct lxc_log_event *event)
cb8c5720 138{
02d25a9e 139 char date[LXC_LOG_DATEFOMAT_SIZE] = "20150427012246";
cb8c5720 140 char buffer[LXC_LOG_BUFFER_SIZE];
02d25a9e 141 const struct tm *t;
cb8c5720 142 int n;
97c94afb 143 int ms;
858377e4 144 int fd_to_use = -1;
42e56013 145
858377e4
SH
146#ifndef NO_LXC_CONF
147 if (!lxc_log_use_global_fd && current_config)
148 fd_to_use = current_config->logfd;
149#endif
150
151 if (fd_to_use == -1)
152 fd_to_use = lxc_log_fd;
153
154 if (fd_to_use == -1)
cb8c5720
CLG
155 return 0;
156
02d25a9e 157 t = localtime(&event->timestamp.tv_sec);
d16ccca8 158 strftime(date, sizeof(date), "%Y%m%d%H%M%S", t);
97c94afb 159 ms = event->timestamp.tv_usec / 1000;
cb8c5720 160 n = snprintf(buffer, sizeof(buffer),
64c57ea1 161 "%15s%s%s %10s.%03d %-8s %s - %s:%s:%d - ",
cb8c5720 162 log_prefix,
64c57ea1
BD
163 log_vmname ? " " : "",
164 log_vmname ? log_vmname : "",
02d25a9e 165 date,
97c94afb 166 ms,
cb8c5720 167 lxc_log_priority_to_string(event->priority),
15bc516e
SH
168 event->category,
169 event->locinfo->file, event->locinfo->func,
170 event->locinfo->line);
cb8c5720
CLG
171
172 n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt,
5fd8380b 173 *event->vap);
cb8c5720
CLG
174
175 if (n >= sizeof(buffer) - 1) {
5fd8380b 176 WARN("truncated next event from %d to %zd bytes", n,
cb8c5720
CLG
177 sizeof(buffer));
178 n = sizeof(buffer) - 1;
179 }
180
181 buffer[n] = '\n';
182
858377e4 183 return write(fd_to_use, buffer, n + 1);
cb8c5720
CLG
184}
185
64c57ea1
BD
186static struct lxc_log_appender log_appender_syslog = {
187 .name = "syslog",
188 .append = log_append_syslog,
189 .next = NULL,
190};
191
d737c074
MN
192static struct lxc_log_appender log_appender_stderr = {
193 .name = "stderr",
194 .append = log_append_stderr,
195 .next = NULL,
196};
197
cb8c5720
CLG
198static struct lxc_log_appender log_appender_logfile = {
199 .name = "logfile",
200 .append = log_append_logfile,
441e4963 201 .next = NULL,
cb8c5720
CLG
202};
203
204static struct lxc_log_category log_root = {
205 .name = "root",
206 .priority = LXC_LOG_PRIORITY_ERROR,
207 .appender = NULL,
208 .parent = NULL,
209};
210
211struct lxc_log_category lxc_log_category_lxc = {
212 .name = "lxc",
213 .priority = LXC_LOG_PRIORITY_ERROR,
858377e4 214 .appender = &log_appender_logfile,
cb8c5720
CLG
215 .parent = &log_root
216};
217
218/*---------------------------------------------------------------------------*/
5e1e7aaf
SH
219static int build_dir(const char *name)
220{
221 char *n = strdup(name); // because we'll be modifying it
222 char *p, *e;
223 int ret;
224
225 if (!n) {
226 ERROR("Out of memory while creating directory '%s'.", name);
227 return -1;
228 }
229
230 e = &n[strlen(n)];
231 for (p = n+1; p < e; p++) {
232 if (*p != '/')
233 continue;
234 *p = '\0';
235 if (access(n, F_OK)) {
236 ret = lxc_unpriv(mkdir(n, 0755));
8479c136 237 if (ret && errno != EEXIST) {
5e1e7aaf
SH
238 SYSERROR("failed to create directory '%s'.", n);
239 free(n);
240 return -1;
241 }
242 }
243 *p = '/';
244 }
245 free(n);
246 return 0;
247}
248
cb8c5720
CLG
249/*---------------------------------------------------------------------------*/
250static int log_open(const char *name)
251{
252 int fd;
253 int newfd;
254
28f602ff
DL
255 fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY |
256 O_APPEND | O_CLOEXEC, 0666));
cb8c5720
CLG
257 if (fd == -1) {
258 ERROR("failed to open log file \"%s\" : %s", name,
259 strerror(errno));
260 return -1;
261 }
262
263 if (fd > 2)
264 return fd;
265
266 newfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
267 if (newfd == -1)
268 ERROR("failed to dup log fd %d : %s", fd, strerror(errno));
269
270 close(fd);
271 return newfd;
272}
273
ab1bf971
DE
274/*
275 * Build the path to the log file
276 * @name : the name of the container
277 * @lxcpath : the lxcpath to use as a basename or NULL to use LOGPATH
ec64264d 278 * Returns malloced path on success, or NULL on failure
ab1bf971
DE
279 */
280static char *build_log_path(const char *name, const char *lxcpath)
5e1e7aaf
SH
281{
282 char *p;
ee25a44f
DE
283 int len, ret, use_dir;
284
74f052dd
SG
285 if (!name)
286 return NULL;
287
ee25a44f
DE
288#if USE_CONFIGPATH_LOGS
289 use_dir = 1;
290#else
291 use_dir = 0;
292#endif
5e1e7aaf
SH
293
294 /*
ee25a44f
DE
295 * If USE_CONFIGPATH_LOGS is true or lxcpath is given, the resulting
296 * path will be:
5e1e7aaf 297 * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
ab1bf971
DE
298 *
299 * If USE_CONFIGPATH_LOGS is false the resulting path will be:
300 * '$logpath' + '/' + '$name' + '.log' + '\0'
5e1e7aaf 301 */
ab1bf971 302 len = strlen(name) + 6; /* 6 == '/' + '.log' + '\0' */
ee25a44f
DE
303 if (lxcpath)
304 use_dir = 1;
305 else
ab1bf971 306 lxcpath = LOGPATH;
ee25a44f
DE
307
308 if (use_dir)
309 len += strlen(lxcpath) + 1 + strlen(name) + 1; /* add "/$container_name/" */
310 else
311 len += strlen(lxcpath) + 1;
5e1e7aaf
SH
312 p = malloc(len);
313 if (!p)
314 return p;
ee25a44f
DE
315
316 if (use_dir)
317 ret = snprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
318 else
319 ret = snprintf(p, len, "%s/%s.log", lxcpath, name);
320
5e1e7aaf
SH
321 if (ret < 0 || ret >= len) {
322 free(p);
323 return NULL;
324 }
325 return p;
326}
327
d9c9b180
SH
328extern void lxc_log_close(void)
329{
64c57ea1
BD
330 closelog();
331 free(log_vmname);
332 log_vmname = NULL;
d9c9b180
SH
333 if (lxc_log_fd == -1)
334 return;
335 close(lxc_log_fd);
336 lxc_log_fd = -1;
337 free(log_fname);
338 log_fname = NULL;
339}
340
ab1bf971
DE
341/*
342 * This can be called:
343 * 1. when a program calls lxc_log_init with no logfile parameter (in which
344 * case the default is used). In this case lxc.logfile can override this.
345 * 2. when a program calls lxc_log_init with a logfile parameter. In this
346 * case we don't want lxc.logfile to override this.
347 * 3. When a lxc.logfile entry is found in config file.
348 */
349static int __lxc_log_set_file(const char *fname, int create_dirs)
350{
351 if (lxc_log_fd != -1) {
352 // we are overriding the default.
d9c9b180 353 lxc_log_close();
ab1bf971
DE
354 }
355
3f53c691
SH
356 assert(fname != NULL);
357
358 if (strlen(fname) == 0) {
6edbfc86
SG
359 log_fname = NULL;
360 return 0;
361 }
362
ab1bf971
DE
363#if USE_CONFIGPATH_LOGS
364 // we don't build_dir for the default if the default is
365 // i.e. /var/lib/lxc/$container/$container.log
366 if (create_dirs)
367#endif
368 if (build_dir(fname)) {
369 ERROR("failed to create dir for log file \"%s\" : %s", fname,
370 strerror(errno));
371 return -1;
372 }
373
374 lxc_log_fd = log_open(fname);
375 if (lxc_log_fd == -1)
376 return -1;
377
378 log_fname = strdup(fname);
379 return 0;
380}
381
382static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_dirs)
383{
384 char *logfile;
385 int ret;
386
387 logfile = build_log_path(name, lxcpath);
388 if (!logfile) {
389 ERROR("could not build log path");
390 return -1;
391 }
392 ret = __lxc_log_set_file(logfile, create_dirs);
393 free(logfile);
394 return ret;
395}
5e1e7aaf 396
64c57ea1
BD
397extern int lxc_log_syslog(int facility)
398{
399 struct lxc_log_appender *appender;
400
401 openlog(log_prefix, LOG_PID, facility);
402 if (!lxc_log_category_lxc.appender) {
403 lxc_log_category_lxc.appender = &log_appender_syslog;
404 return 0;
405 }
406 appender = lxc_log_category_lxc.appender;
407 while (appender->next != NULL)
408 appender = appender->next;
409 appender->next = &log_appender_syslog;
410
411 return 0;
412}
413
414extern void lxc_log_enable_syslog(void)
415{
416 syslog_enable = 1;
417}
418
858377e4
SH
419/*
420 * lxc_log_init:
421 * Called from lxc front-end programs (like lxc-create, lxc-start) to
422 * initalize the log defaults.
423 */
5e1e7aaf 424extern int lxc_log_init(const char *name, const char *file,
ab1bf971
DE
425 const char *priority, const char *prefix, int quiet,
426 const char *lxcpath)
cb8c5720 427{
51cab631 428 int lxc_priority = LXC_LOG_PRIORITY_ERROR;
5e1e7aaf 429 int ret;
51cab631 430
ab1bf971
DE
431 if (lxc_log_fd != -1) {
432 WARN("lxc_log_init called with log already initialized");
2312f31b 433 return 0;
ab1bf971 434 }
2312f31b 435
af61c481 436 if (priority)
b12e1cb5 437 lxc_priority = lxc_log_priority_to_int(priority);
51cab631 438
858377e4
SH
439 if (!lxc_loglevel_specified) {
440 lxc_log_category_lxc.priority = lxc_priority;
441 lxc_loglevel_specified = 1;
442 }
cb8c5720 443
01db0197 444 if (!lxc_quiet_specified) {
01db0197
WD
445 if (!quiet)
446 lxc_log_category_lxc.appender->next = &log_appender_stderr;
447 }
441e4963 448
cb8c5720 449 if (prefix)
ab1bf971 450 lxc_log_set_prefix(prefix);
74476cf1 451
64c57ea1
BD
452 if (name)
453 log_vmname = strdup(name);
454
ab1bf971 455 if (file) {
ab1bf971
DE
456 if (strcmp(file, "none") == 0)
457 return 0;
458 ret = __lxc_log_set_file(file, 1);
858377e4 459 lxc_log_use_global_fd = 1;
5e1e7aaf 460 } else {
74f052dd
SG
461 /* if no name was specified, there nothing to do */
462 if (!name)
463 return 0;
464
ab1bf971
DE
465 ret = -1;
466
e0b0b533
DE
467 if (!lxcpath)
468 lxcpath = LOGPATH;
469
361e0e3c 470 /* try LOGPATH if lxcpath is the default for the privileged containers */
479bba8b 471 if (!geteuid() && strcmp(LXCPATH, lxcpath) == 0)
ab1bf971 472 ret = _lxc_log_set_file(name, NULL, 0);
5e1e7aaf 473
ab1bf971
DE
474 /* try in lxcpath */
475 if (ret < 0)
476 ret = _lxc_log_set_file(name, lxcpath, 1);
477
478 /* try LOGPATH in case its writable by the caller */
479 if (ret < 0)
480 ret = _lxc_log_set_file(name, NULL, 0);
481 }
5e1e7aaf 482
5e1e7aaf 483 /*
ab1bf971
DE
484 * If !file, that is, if the user did not request this logpath, then
485 * ignore failures and continue logging to console
5e1e7aaf 486 */
ab1bf971 487 if (!file && ret != 0) {
5e1e7aaf
SH
488 INFO("Ignoring failure to open default logfile.");
489 ret = 0;
490 }
491
5e1e7aaf 492 return ret;
cb8c5720 493}
4a85ce2a
SH
494
495/*
496 * This is called when we read a lxc.loglevel entry in a lxc.conf file. This
497 * happens after processing command line arguments, which override the .conf
498 * settings. So only set the level if previously unset.
499 */
858377e4 500extern int lxc_log_set_level(int *dest, int level)
4a85ce2a 501{
4a85ce2a
SH
502 if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) {
503 ERROR("invalid log priority %d", level);
504 return -1;
505 }
858377e4 506 *dest = level;
4a85ce2a
SH
507 return 0;
508}
509
ab1bf971
DE
510extern int lxc_log_get_level(void)
511{
ab1bf971
DE
512 return lxc_log_category_lxc.priority;
513}
514
fabf7361
QH
515extern bool lxc_log_has_valid_level(void)
516{
517 int log_level = lxc_log_get_level();
518 if (log_level < 0 || log_level >= LXC_LOG_PRIORITY_NOTSET)
519 return false;
520 return true;
521}
522
4a85ce2a 523/*
ab1bf971
DE
524 * This is called when we read a lxc.logfile entry in a lxc.conf file. This
525 * happens after processing command line arguments, which override the .conf
526 * settings. So only set the file if previously unset.
4a85ce2a 527 */
858377e4 528extern int lxc_log_set_file(int *fd, const char *fname)
4a85ce2a 529{
858377e4
SH
530 if (*fd != -1) {
531 close(*fd);
532 *fd = -1;
533 }
534
535 if (build_dir(fname)) {
536 ERROR("failed to create dir for log file \"%s\" : %s", fname,
537 strerror(errno));
538 return -1;
539 }
540
541 *fd = log_open(fname);
542 if (*fd == -1)
543 return -errno;
544 return 0;
4a85ce2a 545}
9ea87d5d 546
ab1bf971 547extern const char *lxc_log_get_file(void)
5e1e7aaf 548{
ab1bf971 549 return log_fname;
5e1e7aaf
SH
550}
551
ab1bf971 552extern void lxc_log_set_prefix(const char *prefix)
9ea87d5d 553{
ab1bf971
DE
554 strncpy(log_prefix, prefix, sizeof(log_prefix));
555 log_prefix[sizeof(log_prefix) - 1] = 0;
9ea87d5d
SH
556}
557
ab1bf971 558extern const char *lxc_log_get_prefix(void)
9ea87d5d 559{
ab1bf971 560 return log_prefix;
9ea87d5d 561}
6edbfc86
SG
562
563extern void lxc_log_options_no_override()
564{
01db0197 565 lxc_quiet_specified = 1;
858377e4 566 lxc_loglevel_specified = 1;
6edbfc86 567}