From 9cbc4e93b40b452296be6daf0f61a2533630a007 Mon Sep 17 00:00:00 2001 From: Alexander Olekhnovich Date: Thu, 20 Aug 2020 10:00:30 +0200 Subject: journal: add namespace support Add log namespace support which is added since systemd v245 --- systemd/_reader.c | 52 +++++++++++++++++++++++++++++++++++++--------------- systemd/journal.py | 8 ++++---- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/systemd/_reader.c b/systemd/_reader.c index 3b6a4d0..a7699ac 100644 --- a/systemd/_reader.c +++ b/systemd/_reader.c @@ -48,6 +48,12 @@ #define HAVE_HAS_RUNTIME_FILES (LIBSYSTEMD_VERSION >= 229) #define HAVE_HAS_PERSISTENT_FILES (LIBSYSTEMD_VERSION >= 229) +#if LIBSYSTEMD_VERSION >= 245 +# define HAVE_JOURNAL_OPEN_NAMESPACE 1 +#else +# define HAVE_JOURNAL_OPEN_NAMESPACE 0 +#endif + #if LIBSYSTEMD_VERSION >= 230 # define HAVE_JOURNAL_OPEN_DIRECTORY_FD 1 #else @@ -89,17 +95,17 @@ static PyStructSequence_Desc Monotonic_desc = { * Convert a str or bytes object into a C-string path. * Returns NULL on error. */ -static char* convert_path(PyObject *path, PyObject **bytes) { +static char* str_converter(PyObject *str, PyObject **bytes) { #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1 int r; - r = PyUnicode_FSConverter(path, bytes); + r = PyUnicode_FSConverter(str, bytes); if (r == 0) return NULL; return PyBytes_AsString(*bytes); #else - return PyString_AsString(path); + return PyString_AsString(str); #endif } @@ -146,7 +152,7 @@ static int strv_converter(PyObject* obj, void *_result) { char *s; item = PySequence_ITEM(obj, i); - s = convert_path(item, &bytes); + s = str_converter(item, &bytes); if (!s) goto cleanup; @@ -225,7 +231,7 @@ static void Reader_dealloc(Reader* self) { } PyDoc_STRVAR(Reader__doc__, - "_Reader([flags | path | files]) -> ...\n\n" + "_Reader([flags | path | files | namespace]) -> ...\n\n" "_Reader allows filtering and retrieval of Journal entries.\n" "Note: this is a low-level interface, and probably not what you\n" "want, use systemd.journal.Reader instead.\n\n" @@ -236,23 +242,25 @@ PyDoc_STRVAR(Reader__doc__, "OS_ROOT is used to open the journal from directories relative to the specified\n" "directory path or file descriptor.\n" "\n" - "Instead of opening the system journal, argument `path` may specify a directory\n" - "which contains the journal. It maybe be either a file system path (a string), or\n" - "a file descriptor (an integer). Alternatively, argument `files` may specify a list\n" - "of journal file names. Note that `flags`, `path`, `files`, `directory_fd` are\n" - "exclusive.\n\n" + "If `namespace` argument is specified, the specific journal namespace will be open\n" + "(supported since systemd v245). Instead of opening the system journal, argument\n" + "`path` may specify a directory which contains the journal. It maybe be either\n" + "a file system path (a string), or a file descriptor (an integer). Alternatively,\n" + "argument `files` may specify a list of journal file names. Note that `flags`, `path`,\n" + "`files`, `directory_fd`, `namespace` are exclusive.\n\n" "_Reader implements the context manager protocol: the journal will be closed when\n" "exiting the block."); static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) { unsigned flags = SD_JOURNAL_LOCAL_ONLY; - PyObject *_path = NULL, *_files = NULL; + PyObject *_path = NULL, *_files = NULL, *_namespace = NULL; int r; - static const char* const kwlist[] = {"flags", "path", "files", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iO&O&:__init__", (char**) kwlist, + static const char* const kwlist[] = {"flags", "path", "files", "namespace", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iO&O&O&:__init__", (char**) kwlist, &flags, null_converter, &_path, - null_converter, &_files)) + null_converter, &_files, + null_converter, &_namespace)) return -1; if (!!_path + !!_files > 1) { @@ -279,7 +287,7 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) { char *path = NULL; _cleanup_Py_DECREF_ PyObject *path_bytes = NULL; - path = convert_path(_path, &path_bytes); + path = str_converter(_path, &path_bytes); if (!path) return -1; @@ -319,6 +327,20 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) { r = -ENOSYS; #endif } + } else if (_namespace) { +#if HAVE_JOURNAL_OPEN_NAMESPACE + char *namespace = NULL; + _cleanup_Py_DECREF_ PyObject *ns_bytes = NULL; + namespace = str_converter(_namespace, &ns_bytes); + if (!namespace) + return -1; + + Py_BEGIN_ALLOW_THREADS + r = sd_journal_open_namespace(&self->j, namespace, flags); + Py_END_ALLOW_THREADS +#else + r = -ENOSYS; +#endif } else { Py_BEGIN_ALLOW_THREADS r = sd_journal_open(&self->j, flags); diff --git a/systemd/journal.py b/systemd/journal.py index 64502ce..c6b3a01 100644 --- a/systemd/journal.py +++ b/systemd/journal.py @@ -140,7 +140,7 @@ class Reader(_Reader): journal. """ - def __init__(self, flags=None, path=None, files=None, converters=None): + def __init__(self, flags=None, path=None, files=None, converters=None, namespace=None): """Create a new Reader. Argument `flags` defines the open flags of the journal, which can be one @@ -149,8 +149,8 @@ class Reader(_Reader): and SYSTEM_ONLY opens only journal files of system services and the kernel. Argument `path` is the directory of journal files, either a file system - path or a file descriptor. Note that `flags`, `path`, and `files` are - exclusive. + path or a file descriptor. Specify `namespace` to read from specific journal + namespace. Note that `flags`, `path`, `files` and `namespace` are exclusive. Argument `converters` is a dictionary which updates the DEFAULT_CONVERTERS to convert journal field values. Field names are used @@ -171,7 +171,7 @@ class Reader(_Reader): else: flags = 0 - super(Reader, self).__init__(flags, path, files) + super(Reader, self).__init__(flags, path, files, namespace) if _sys.version_info >= (3, 3): self.converters = _ChainMap() if converters is not None: -- cgit v1.2.1