From 5cb7f294f6a5a8b4a68e940c30ca9af0fe0741d5 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 27 Jul 2013 15:28:50 +0100 Subject: [PATCH] New APIs: Add systemd journal support (RHBZ#988100). This adds simple support for reading the journal files from guests that use the systemd journal. The new APIs are: journal-open journal-close journal-next journal-skip journal-get journal-get-data-threshold journal-set-data-threshold internal-journal-get More complex journal support (eg. for seeking within the journal, support for cursors) could be added later. --- README | 2 + configure.ac | 8 ++ daemon/Makefile.am | 3 + daemon/journal.c | 219 +++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 116 +++++++++++++++++++++++ po/POTFILES | 2 + src/MAX_PROC_NR | 2 +- src/Makefile.am | 1 + src/guestfs.pod | 9 ++ src/journal.c | 154 ++++++++++++++++++++++++++++++ 10 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 daemon/journal.c create mode 100644 src/journal.c diff --git a/README b/README index 53bf414eb..4c54f0c57 100644 --- a/README +++ b/README @@ -139,6 +139,8 @@ The full requirements are described below. | libldm | | O | Library (libldm) and 'ldmtool' for | | | | | handling Windows Dynamic Disks. | +--------------+-------------+---+-----------------------------------------+ +| sd-journal | | O | systemd journal library | ++--------------+-------------+---+-----------------------------------------+ | yajl | 2 | O | JSON parser for parsing output of | | | | | ldmtool and qemu-img info commands. | +--------------+-------------+---+-----------------------------------------+ diff --git a/configure.ac b/configure.ac index ab90db1c1..4b558e63c 100644 --- a/configure.ac +++ b/configure.ac @@ -876,6 +876,14 @@ PKG_CHECK_MODULES([HIVEX], [hivex],[ [AC_MSG_WARN([hivex not found, some core features will be disabled])]) AM_CONDITIONAL([HAVE_HIVEX],[test "x$HIVEX_LIBS" != "x"]) +dnl systemd journal library (optional) +PKG_CHECK_MODULES([SD_JOURNAL], [libsystemd-journal],[ + AC_SUBST([SD_JOURNAL_CFLAGS]) + AC_SUBST([SD_JOURNAL_LIBS]) + AC_DEFINE([HAVE_SD_JOURNAL],[1],[systemd journal library found at compile time.]) +], + [AC_MSG_WARN([systemd journal library not found, some features will be disabled])]) + dnl FUSE is optional to build the FUSE module. AC_ARG_ENABLE([fuse], AS_HELP_STRING([--disable-fuse], [disable FUSE (guestmount) support]), diff --git a/daemon/Makefile.am b/daemon/Makefile.am index d077dab83..b0e4959df 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -125,6 +125,7 @@ guestfsd_SOURCES = \ internal.c \ is.c \ isoinfo.c \ + journal.c \ labels.c \ ldm.c \ link.c \ @@ -184,6 +185,7 @@ guestfsd_LDADD = \ $(SELINUX_LIB) \ $(AUGEAS_LIBS) \ $(HIVEX_LIBS) \ + $(SD_JOURNAL_LIBS) \ $(top_builddir)/gnulib/lib/.libs/libgnu.a \ $(GETADDRINFO_LIB) \ $(HOSTENT_LIB) \ @@ -203,6 +205,7 @@ guestfsd_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ $(AUGEAS_CFLAGS) \ $(HIVEX_CFLAGS) \ + $(SD_JOURNAL_CFLAGS) \ $(YAJL_CFLAGS) \ $(PCRE_CFLAGS) diff --git a/daemon/journal.c b/daemon/journal.c new file mode 100644 index 000000000..a0290bf88 --- /dev/null +++ b/daemon/journal.c @@ -0,0 +1,219 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2013 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include +#include +#include +#include + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" +#include "optgroups.h" + +#ifdef HAVE_SD_JOURNAL + +#include + +int +optgroup_journal_available (void) +{ + return 1; +} + +/* The handle. As with Augeas and hivex, there is one per guestfs + * handle / daemon. + */ +static sd_journal *j = NULL; + +/* Clean up the handle on daemon exit. */ +static void journal_finalize (void) __attribute__((destructor)); +static void +journal_finalize (void) +{ + if (j) { + sd_journal_close (j); + j = NULL; + } +} + +#define NEED_HANDLE(errcode) \ + do { \ + if (!j) { \ + reply_with_error ("%s: you must call 'journal-open' first to initialize the journal handle", __func__); \ + return (errcode); \ + } \ + } \ + while (0) + +int +do_journal_open (const char *directory) +{ + CLEANUP_FREE char *buf = NULL; + int r; + + if (j) { + sd_journal_close (j); + j = NULL; + } + + buf = sysroot_path (directory); + if (!buf) { + reply_with_perror ("malloc"); + return -1; + } + + r = sd_journal_open_directory (&j, buf, 0); + if (r < 0) { + reply_with_perror_errno (-r, "sd_journal_open_directory: %s", directory); + return -1; + } + + return 0; +} + +int +do_journal_close (void) +{ + NEED_HANDLE (-1); + + sd_journal_close (j); + j = NULL; + + return 0; +} + +int +do_journal_next (void) +{ + int r; + + NEED_HANDLE (-1); + + r = sd_journal_next (j); + if (r < 0) { + reply_with_perror_errno (-r, "sd_journal_next"); + return -1; + } + + return r != 0; +} + +int64_t +do_journal_skip (int64_t skip) +{ + int r; + + NEED_HANDLE (-1); + + if (skip == 0) + return 0; + + if (skip > 0) + r = sd_journal_next_skip (j, (uint64_t) skip); + else /* skip < 0 */ + r = sd_journal_previous_skip (j, (uint64_t) -skip); + if (r < 0) { + reply_with_perror_errno (-r, "failed to skip %zd journal entries", skip); + return -1; + } + + return r; +} + +/* Has one FileOut parameter. */ +int +do_internal_journal_get (void) +{ + const void *data; + size_t len; + uint64_t len_be; + int r; + + NEED_HANDLE (-1); + + /* Now we must send the reply message, before the filenames. After + * this there is no opportunity in the protocol to send any error + * message back. Instead we can only cancel the transfer. + */ + reply (NULL, NULL); + + sd_journal_restart_data (j); + while ((r = sd_journal_enumerate_data (j, &data, &len)) > 0) { + //fprintf (stderr, "data[%zu] = %.*s\n", len, (int) len, (char*) data); + len_be = htobe64 ((uint64_t) len); + if (send_file_write (&len_be, sizeof (len_be)) < 0) + return -1; + if (send_file_write (data, len) < 0) + return -1; + } + + /* Failure while enumerating the fields. */ + if (r < 0) { + send_file_end (1); /* Cancel. */ + errno = -r; + perror ("sd_journal_enumerate_data"); + return -1; + } + + /* Normal end of file. */ + if (send_file_end (0)) + return -1; + return 0; +} + +int64_t +do_journal_get_data_threshold (void) +{ + int r; + size_t ret; + + NEED_HANDLE (-1); + + r = sd_journal_get_data_threshold (j, &ret); + if (r < 0) { + reply_with_perror_errno (-r, "sd_journal_get_data_threshold"); + return -1; + } + + return ret; +} + +int +do_journal_set_data_threshold (int64_t threshold) +{ + int r; + + NEED_HANDLE (-1); + + r = sd_journal_set_data_threshold (j, threshold); + if (r < 0) { + reply_with_perror_errno (-r, "sd_journal_set_data_threshold"); + return -1; + } + + return 0; +} + +#else /* !HAVE_SD_JOURNAL */ + +OPTGROUP_SD_JOURNAL_NOT_AVAILABLE + +#endif /* !HAVE_SD_JOURNAL */ diff --git a/generator/actions.ml b/generator/actions.ml index fc3f7f774..93caf5253 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -2969,6 +2969,28 @@ writing to it). The drive is deleted when the handle is closed. The optional arguments C and C