From 8c823a038cdadb42ea270f22341136990de295da Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Tue, 12 Nov 2024 13:53:13 +0100 Subject: [PATCH 1/8] meson: introduce PROJECT_VERSION_STR and use it in udev --- meson.build | 2 ++ src/udev/udev-ctrl.c | 2 +- src/udev/udevadm.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 48b8b058349..ebe24c6290f 100644 --- a/meson.build +++ b/meson.build @@ -33,6 +33,8 @@ conf = configuration_data() conf.set_quoted('PROJECT_URL', 'https://systemd.io/') conf.set('PROJECT_VERSION', project_major_version, description : 'Numerical project version (used where a simple number is expected)') +conf.set_quoted('PROJECT_VERSION_STR', project_major_version, + description: 'Stringified project version (used where a simple string is expected)') conf.set_quoted('PROJECT_VERSION_FULL', meson.project_version(), description : 'Full project version') relative_source_path = run_command('realpath', diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index 1914bf7929f..10dd48164a2 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -293,7 +293,7 @@ int udev_ctrl_start(UdevCtrl *uctrl, udev_ctrl_handler_t callback, void *userdat int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, const void *data) { UdevCtrlMessageWire ctrl_msg_wire = { - .version = "udev-" STRINGIFY(PROJECT_VERSION), + .version = "udev-" PROJECT_VERSION_STR, .magic = UDEV_CTRL_MAGIC, .type = type, }; diff --git a/src/udev/udevadm.h b/src/udev/udevadm.h index e39dbf655d4..665d2f46b37 100644 --- a/src/udev/udevadm.h +++ b/src/udev/udevadm.h @@ -20,6 +20,6 @@ int lock_main(int argc, char *argv[], void *userdata); static inline int print_version(void) { /* Dracut relies on the version being a single integer */ - puts(STRINGIFY(PROJECT_VERSION)); + puts(PROJECT_VERSION_STR); return 0; } From 92e8e2b034a896b92ed74365f560918dc5bf0b5e Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Tue, 12 Nov 2024 13:46:20 +0100 Subject: [PATCH 2/8] log: log_get_target_max_level() --- src/basic/log.c | 6 ++++++ src/basic/log.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/basic/log.c b/src/basic/log.c index 982b2473267..02211460b57 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -1409,6 +1409,12 @@ int log_get_max_level(void) { return log_max_level; } +int log_get_target_max_level(LogTarget target) { + assert(target >= 0); + assert(target < _LOG_TARGET_SINGLE_MAX); + return log_target_max_level[target]; +} + void log_show_color(bool b) { show_color = b; } diff --git a/src/basic/log.h b/src/basic/log.h index 8703a363c0c..07f187a24a9 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -59,6 +59,7 @@ void log_settle_target(void); int log_set_max_level(int level); int log_set_max_level_from_string(const char *e); int log_get_max_level(void) _pure_; +int log_get_target_max_level(LogTarget target); int log_max_levels_to_string(int level, char **ret); void log_set_facility(int facility); From ea6075a26e29dbda7a47d65715e4cdf7790a2c98 Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Thu, 6 Mar 2025 08:37:10 -0800 Subject: [PATCH 3/8] core: common rlimits code and structures --- src/core/meson.build | 1 + src/core/varlink-common.c | 53 +++++++++++++++++++++++++++++++++ src/core/varlink-common.h | 8 +++++ src/shared/varlink-idl-common.c | 34 +++++++++++++++++++++ src/shared/varlink-idl-common.h | 3 ++ 5 files changed, 99 insertions(+) create mode 100644 src/core/varlink-common.c create mode 100644 src/core/varlink-common.h diff --git a/src/core/meson.build b/src/core/meson.build index 500fb13f9ba..c40893223de 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -63,6 +63,7 @@ libcore_sources = files( 'unit-serialize.c', 'unit.c', 'varlink.c', + 'varlink-common.c', ) subdir('bpf/socket_bind') diff --git a/src/core/varlink-common.c b/src/core/varlink-common.c new file mode 100644 index 00000000000..eb3fafa2fa9 --- /dev/null +++ b/src/core/varlink-common.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "json-util.h" +#include "rlimit-util.h" +#include "varlink-common.h" + +int rlimit_build_json(sd_json_variant **ret, const char *name, void *userdata) { + const struct rlimit *rl = userdata; + struct rlimit buf = {}; + + assert(ret); + assert(name); + + if (!rl) { + int z = rlimit_from_string(name); + if (z < 0) + return log_debug_errno(z, "Failed to get rlimit for '%s': %m", name); + + if (getrlimit(z, &buf) < 0) { + log_debug_errno(errno, "Failed to getrlimit(%s), ignoring: %m", name); + *ret = NULL; + return 0; + } + + rl = &buf; + } + + if (rl->rlim_cur == RLIM_INFINITY && rl->rlim_max == RLIM_INFINITY) { + *ret = NULL; + return 0; + } + + return sd_json_buildo(ret, + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("soft", rl->rlim_cur, RLIM_INFINITY), + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("hard", rl->rlim_max, RLIM_INFINITY)); +} + +int rlimit_table_build_json(sd_json_variant **ret, const char *name, void *userdata) { + struct rlimit **rl = ASSERT_PTR(userdata); + int r; + + assert(ret); + + for (int i = 0; i < _RLIMIT_MAX; i++) { + r = sd_json_variant_merge_objectbo( + ret, + JSON_BUILD_PAIR_CALLBACK_NON_NULL(rlimit_to_string(i), rlimit_build_json, rl[i])); + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/core/varlink-common.h b/src/core/varlink-common.h new file mode 100644 index 00000000000..94a8682a218 --- /dev/null +++ b/src/core/varlink-common.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "sd-json.h" +#include "sd-varlink.h" + +int rlimit_build_json(sd_json_variant **ret, const char *name, void *userdata); +int rlimit_table_build_json(sd_json_variant **ret, const char *name, void *userdata); diff --git a/src/shared/varlink-idl-common.c b/src/shared/varlink-idl-common.c index e48fd46e0f5..a20ec4c4296 100644 --- a/src/shared/varlink-idl-common.c +++ b/src/shared/varlink-idl-common.c @@ -19,3 +19,37 @@ SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(pidfdId, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Boot ID of the system the inode number belongs to"), SD_VARLINK_DEFINE_FIELD(bootId, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + +SD_VARLINK_DEFINE_STRUCT_TYPE( + RateLimit, + SD_VARLINK_FIELD_COMMENT("The ratelimit interval"), + SD_VARLINK_DEFINE_FIELD(intervalUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The ratelimit burst"), + SD_VARLINK_DEFINE_FIELD(burst, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + +SD_VARLINK_DEFINE_STRUCT_TYPE( + ResourceLimit, + SD_VARLINK_FIELD_COMMENT("The soft resource limit. RLIM_INFINITY is mapped to unset value"), + SD_VARLINK_DEFINE_FIELD(soft, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The hard resource limit. RLIM_INFINITY is mapped to unset value"), + SD_VARLINK_DEFINE_FIELD(hard, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + +SD_VARLINK_DEFINE_STRUCT_TYPE( + ResourceLimitTable, + SD_VARLINK_FIELD_COMMENT("See setrlimit(2) for details"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(CPU, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(FSIZE, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(DATA, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(STACK, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(CORE, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RSS, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(NOFILE, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(AS, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(NPROC, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(MEMLOCK, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LOCKS, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SIGPENDING, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(MSGQUEUE, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(NICE, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RTPRIO, ResourceLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RTTIME, ResourceLimit, SD_VARLINK_NULLABLE)); diff --git a/src/shared/varlink-idl-common.h b/src/shared/varlink-idl-common.h index 91b643f8100..de5177de4b3 100644 --- a/src/shared/varlink-idl-common.h +++ b/src/shared/varlink-idl-common.h @@ -5,3 +5,6 @@ extern const sd_varlink_symbol vl_type_Timestamp; extern const sd_varlink_symbol vl_type_ProcessId; +extern const sd_varlink_symbol vl_type_RateLimit; +extern const sd_varlink_symbol vl_type_ResourceLimit; +extern const sd_varlink_symbol vl_type_ResourceLimitTable; From e739395f13f4512a658e486e1145c4c8fcab860a Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Mon, 12 May 2025 04:17:38 -0700 Subject: [PATCH 4/8] socket-util: socket_address_equal_unix() --- src/basic/socket-util.c | 18 ++++++++++++++++++ src/basic/socket-util.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 5e6195e108e..2c003106c9f 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1797,6 +1797,24 @@ int socket_address_parse_unix(SocketAddress *ret_address, const char *s) { return 0; } +int socket_address_equal_unix(const char *a, const char *b) { + SocketAddress socket_a, socket_b; + int r; + + assert(a); + assert(b); + + r = socket_address_parse_unix(&socket_a, a); + if (r < 0) + return r; + + r = socket_address_parse_unix(&socket_b, b); + if (r < 0) + return r; + + return sockaddr_equal(&socket_a.sockaddr, &socket_b.sockaddr); +} + int vsock_parse_port(const char *s, unsigned *ret) { int r; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index e9671c38333..830b48e435f 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -342,6 +342,7 @@ int vsock_parse_cid(const char *s, unsigned *ret); * protocol mismatch. */ int socket_address_parse_unix(SocketAddress *ret_address, const char *s); int socket_address_parse_vsock(SocketAddress *ret_address, const char *s); +int socket_address_equal_unix(const char *a, const char *b); /* libc's SOMAXCONN is defined to 128 or 4096 (at least on glibc). But actually, the value can be much * larger. In our codebase we want to set it to the max usually, since nowadays socket memory is properly From c7728d2b46a2cc0e1b172024118970b8c4059f68 Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Mon, 12 May 2025 04:18:00 -0700 Subject: [PATCH 5/8] shared: varlink_server_contains_socket() --- src/shared/varlink-serialize.c | 18 ++++++++++++++++++ src/shared/varlink-serialize.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/shared/varlink-serialize.c b/src/shared/varlink-serialize.c index 57a8d7908ea..075cb6cc5e1 100644 --- a/src/shared/varlink-serialize.c +++ b/src/shared/varlink-serialize.c @@ -2,6 +2,7 @@ #include "log.h" #include "parse-util.h" +#include "socket-util.h" #include "varlink-internal.h" #include "varlink-serialize.h" @@ -84,3 +85,20 @@ int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSe LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss)); return 0; } + +bool varlink_server_contains_socket(sd_varlink_server *s, const char *address) { + int r; + + assert(s); + assert(address); + + LIST_FOREACH(sockets, ss, s->sockets) { + r = socket_address_equal_unix(ss->address, address); + if (r < 0) + log_debug_errno(r, "Failed to compare '%s' and '%s', ignoring: %m", ss->address, address); + if (r > 0) + return true; + } + + return false; +} diff --git a/src/shared/varlink-serialize.h b/src/shared/varlink-serialize.h index 149aa88b112..4cc47aa0536 100644 --- a/src/shared/varlink-serialize.h +++ b/src/shared/varlink-serialize.h @@ -9,3 +9,5 @@ int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds); int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds); + +bool varlink_server_contains_socket(sd_varlink_server *s, const char *address); From 50243880058beca246cb1c02e8bc0fd2034cb934 Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Fri, 7 Mar 2025 01:04:14 -0800 Subject: [PATCH 6/8] shared: watchdog_get_last_ping_as_dual_timestamp() --- src/shared/watchdog.c | 9 +++++++++ src/shared/watchdog.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c index f00ff25ab20..28cae1c2608 100644 --- a/src/shared/watchdog.c +++ b/src/shared/watchdog.c @@ -206,6 +206,15 @@ usec_t watchdog_get_last_ping(clockid_t clock) { return map_clock_usec(watchdog_last_good_ping, CLOCK_BOOTTIME, clock); } +dual_timestamp* watchdog_get_last_ping_as_dual_timestamp(dual_timestamp *ret) { + assert(ret); + + ret->monotonic = watchdog_get_last_ping(CLOCK_MONOTONIC); + ret->realtime = watchdog_get_last_ping(CLOCK_REALTIME); + + return ret; +} + static int watchdog_ping_now(void) { int r; diff --git a/src/shared/watchdog.h b/src/shared/watchdog.h index c0fcccbd073..7880b041282 100644 --- a/src/shared/watchdog.h +++ b/src/shared/watchdog.h @@ -7,6 +7,7 @@ const char* watchdog_get_device(void); usec_t watchdog_get_last_ping(clockid_t clock); +dual_timestamp* watchdog_get_last_ping_as_dual_timestamp(dual_timestamp *ret); int watchdog_set_device(const char *path); int watchdog_setup(usec_t timeout); From 736349958efe34089131ca88950e2e5bb391d36a Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Thu, 6 Mar 2025 08:40:49 -0800 Subject: [PATCH 7/8] core: introduce io.systemd.Manager.Describe method Let's extend pid1's varlink interface and add a Describe method to get the global Manager object information as a JSON object (io.systemd.Manager.Describe). Because the new varlink interface should be available on both the user managers and the system manager, we also make the necessary changes to expose a varlink server on user managers. --- src/core/manager-serialize.c | 2 +- src/core/manager-varlink.c | 171 +++++++++++++++++++++ src/core/manager-varlink.h | 7 + src/core/meson.build | 1 + src/core/varlink.c | 90 +++++++---- src/shared/meson.build | 1 + src/shared/varlink-io.systemd.Manager.c | 191 ++++++++++++++++++++++++ src/shared/varlink-io.systemd.Manager.h | 6 + 8 files changed, 439 insertions(+), 30 deletions(-) create mode 100644 src/core/manager-varlink.c create mode 100644 src/core/manager-varlink.h create mode 100644 src/shared/varlink-io.systemd.Manager.c create mode 100644 src/shared/varlink-io.systemd.Manager.h diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 28bf7f5f7bc..e0199a3727d 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -485,7 +485,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { if (r < 0) return r; } else if ((val = startswith(l, "varlink-server-socket-address="))) { - if (!m->varlink_server && MANAGER_IS_SYSTEM(m)) { + if (!m->varlink_server) { r = manager_setup_varlink_server(m); if (r < 0) { log_warning_errno(r, "Failed to setup varlink server, ignoring: %m"); diff --git a/src/core/manager-varlink.c b/src/core/manager-varlink.c new file mode 100644 index 00000000000..c124b2fc9fc --- /dev/null +++ b/src/core/manager-varlink.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "build.h" +#include "confidential-virt.h" +#include "json-util.h" +#include "manager-varlink.h" +#include "manager.h" +#include "syslog-util.h" +#include "taint.h" +#include "version.h" +#include "varlink-common.h" +#include "virt.h" +#include "watchdog.h" + +static int manager_environment_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = ASSERT_PTR(userdata); + int r; + + assert(ret); + + r = manager_get_effective_environment(m, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_array_strv(ret, l); +} + +static int manager_context_build_json(sd_json_variant **ret, const char *name, void *userdata) { + Manager *m = ASSERT_PTR(userdata); + _cleanup_strv_free_ char **taints = NULL; + + taints = taint_strv(); + if (!taints) + return -ENOMEM; + + return sd_json_buildo(ASSERT_PTR(ret), + SD_JSON_BUILD_PAIR_STRING("Version", GIT_VERSION), + SD_JSON_BUILD_PAIR_STRING("Architecture", architecture_to_string(uname_architecture())), + SD_JSON_BUILD_PAIR_STRING("Features", systemd_features), + JSON_BUILD_PAIR_STRV_NON_EMPTY("Taints", taints), + SD_JSON_BUILD_PAIR_STRV("UnitPath", m->lookup_paths.search_path), + JSON_BUILD_PAIR_STRV_NON_EMPTY("Environment", m->transient_environment), + SD_JSON_BUILD_PAIR_STRING("DefaultStandardOutput", exec_output_to_string(m->defaults.std_output)), + SD_JSON_BUILD_PAIR_STRING("DefaultStandardError", exec_output_to_string(m->defaults.std_error)), + SD_JSON_BUILD_PAIR_BOOLEAN("ServiceWatchdogs", m->service_watchdogs), + JSON_BUILD_PAIR_FINITE_USEC("DefaultTimerAccuracyUSec", m->defaults.timer_accuracy_usec), + JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutStartUSec", m->defaults.timeout_start_usec), + JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutStopUSec", m->defaults.timeout_stop_usec), + JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutAbortUSec", manager_default_timeout_abort_usec(m)), + JSON_BUILD_PAIR_FINITE_USEC("DefaultDeviceTimeoutUSec", m->defaults.device_timeout_usec), + JSON_BUILD_PAIR_FINITE_USEC("DefaultRestartUSec", m->defaults.restart_usec), + JSON_BUILD_PAIR_RATELIMIT("DefaultStartLimit", &m->defaults.start_limit), + SD_JSON_BUILD_PAIR_BOOLEAN("DefaultCPUAccounting", m->defaults.cpu_accounting), + SD_JSON_BUILD_PAIR_BOOLEAN("DefaultBlockIOAccounting", m->defaults.blockio_accounting), + SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIOAccounting", m->defaults.io_accounting), + SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIPAccounting", m->defaults.ip_accounting), + SD_JSON_BUILD_PAIR_BOOLEAN("DefaultMemoryAccounting", m->defaults.memory_accounting), + SD_JSON_BUILD_PAIR_BOOLEAN("DefaultTasksAccounting", m->defaults.tasks_accounting), + SD_JSON_BUILD_PAIR_CALLBACK("DefaultLimits", rlimit_table_build_json, m->defaults.rlimit), + SD_JSON_BUILD_PAIR_UNSIGNED("DefaultTasksMax", cgroup_tasks_max_resolve(&m->defaults.tasks_max)), + JSON_BUILD_PAIR_FINITE_USEC("DefaultMemoryPressureThresholdUSec", m->defaults.memory_pressure_threshold_usec), + SD_JSON_BUILD_PAIR_STRING("DefaultMemoryPressureWatch", cgroup_pressure_watch_to_string(m->defaults.memory_pressure_watch)), + JSON_BUILD_PAIR_FINITE_USEC("TimerSlackNSec", (uint64_t) prctl(PR_GET_TIMERSLACK)), + SD_JSON_BUILD_PAIR_STRING("DefaultOOMPolicy", oom_policy_to_string(m->defaults.oom_policy)), + SD_JSON_BUILD_PAIR_INTEGER("DefaultOOMScoreAdjust", m->defaults.oom_score_adjust), + SD_JSON_BUILD_PAIR_STRING("CtrlAltDelBurstAction", emergency_action_to_string(m->cad_burst_action))); +} + +static int log_level_build_runtime_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + int log_max_level = log_get_max_level(); + int r; + + assert(ret); + + for (LogTarget log_target = 0; log_target < _LOG_TARGET_SINGLE_MAX; log_target++) { + _cleanup_free_ char *log_level_string = NULL; + + int target_max_level = log_get_target_max_level(log_target); + const char *log_target_string = log_target_to_string(log_target); + + int log_level = MIN(log_max_level, target_max_level); + r = log_level_to_string_alloc(log_level, &log_level_string); + if (r < 0) + return r; + + r = sd_json_variant_set_field_string(&v, log_target_string, log_level_string); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int manager_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) { + Manager *m = ASSERT_PTR(userdata); + dual_timestamp watchdog_last_ping; + + return sd_json_buildo(ASSERT_PTR(ret), + SD_JSON_BUILD_PAIR_STRING("Virtualization", virtualization_to_string(detect_virtualization())), + SD_JSON_BUILD_PAIR_STRING("ConfidentialVirtualization", confidential_virtualization_to_string(detect_confidential_virtualization())), + JSON_BUILD_PAIR_STRING_NON_EMPTY("ConfirmSpawn", manager_get_confirm_spawn(m)), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("FirmwareTimestamp", &m->timestamps[MANAGER_TIMESTAMP_FIRMWARE]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("LoaderTimestamp", &m->timestamps[MANAGER_TIMESTAMP_LOADER]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("KernelTimestamp", &m->timestamps[MANAGER_TIMESTAMP_KERNEL]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("UserspaceTimestamp", &m->timestamps[MANAGER_TIMESTAMP_USERSPACE]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("FinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_FINISH]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("SecurityStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_SECURITY_START]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("SecurityFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_SECURITY_FINISH]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("GeneratorsStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_GENERATORS_START]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("GeneratorsFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_GENERATORS_FINISH]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("UnitsLoadStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_START]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("UnitsLoadFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("UnitsLoadTimestamp", &m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDSecurityStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_SECURITY_START]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDSecurityFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDGeneratorsStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_START]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDGeneratorsFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDUnitsLoadStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START]), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDUnitsLoadFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH]), + SD_JSON_BUILD_PAIR_BOOLEAN("ShowStatus", manager_get_show_status_on(m)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogLevel", log_level_build_runtime_json, m), + SD_JSON_BUILD_PAIR_STRING("LogTarget", log_target_to_string(log_get_target())), + SD_JSON_BUILD_PAIR_UNSIGNED("NNames", hashmap_size(m->units)), + SD_JSON_BUILD_PAIR_UNSIGNED("NFailedUnits", set_size(m->failed_units)), + SD_JSON_BUILD_PAIR_UNSIGNED("NJobs", hashmap_size(m->jobs)), + SD_JSON_BUILD_PAIR_UNSIGNED("NInstalledJobs", m->n_installed_jobs), + SD_JSON_BUILD_PAIR_UNSIGNED("NFailedJobs", m->n_failed_jobs), + SD_JSON_BUILD_PAIR_REAL("Progress", manager_get_progress(m)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("Environment", manager_environment_build_json, m), + JSON_BUILD_PAIR_STRING_NON_EMPTY("WatchdogDevice", watchdog_get_device()), + JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("WatchdogLastPingTimestamp", watchdog_get_last_ping_as_dual_timestamp(&watchdog_last_ping)), + JSON_BUILD_PAIR_STRING_NON_EMPTY("ControlGroup", m->cgroup_root), + SD_JSON_BUILD_PAIR_STRING("SystemState", manager_state_to_string(manager_state(m))), + SD_JSON_BUILD_PAIR_UNSIGNED("ExitCode", m->return_value), + JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogUSec", manager_get_watchdog(m, WATCHDOG_RUNTIME)), + JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogPreUSec", manager_get_watchdog(m, WATCHDOG_PRETIMEOUT)), + JSON_BUILD_PAIR_STRING_NON_EMPTY("RuntimeWatchdogPreGovernor", m->watchdog_pretimeout_governor), + JSON_BUILD_PAIR_FINITE_USEC("RebootWatchdogUSec", manager_get_watchdog(m, WATCHDOG_REBOOT)), + JSON_BUILD_PAIR_FINITE_USEC("KExecWatchdogUSec", manager_get_watchdog(m, WATCHDOG_KEXEC)), + SD_JSON_BUILD_PAIR_UNSIGNED("SoftRebootsCount", m->soft_reboots_count)); +} + +int vl_method_describe_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + Manager *manager = ASSERT_PTR(userdata); + int r; + + assert(parameters); + + if (sd_json_variant_elements(parameters) > 0) + return sd_varlink_error_invalid_parameter(link, parameters); + + r = sd_json_buildo(&v, + SD_JSON_BUILD_PAIR_CALLBACK("Context", manager_context_build_json, manager), + SD_JSON_BUILD_PAIR_CALLBACK("Runtime", manager_runtime_build_json, manager)); + if (r < 0) + return log_error_errno(r, "Failed to build manager JSON data: %m"); + + return sd_varlink_reply(link, v); +} diff --git a/src/core/manager-varlink.h b/src/core/manager-varlink.h new file mode 100644 index 00000000000..52be44502b4 --- /dev/null +++ b/src/core/manager-varlink.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "sd-json.h" +#include "sd-varlink.h" + +int vl_method_describe_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); diff --git a/src/core/meson.build b/src/core/meson.build index c40893223de..659dc9b7ea5 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -43,6 +43,7 @@ libcore_sources = files( 'load-fragment.c', 'manager-dump.c', 'manager-serialize.c', + 'manager-varlink.c', 'manager.c', 'mount.c', 'namespace.c', diff --git a/src/core/varlink.c b/src/core/varlink.c index c555b2721af..40b988aec51 100644 --- a/src/core/varlink.c +++ b/src/core/varlink.c @@ -3,17 +3,21 @@ #include "sd-varlink.h" #include "dynamic-user.h" +#include "format-util.h" #include "json-util.h" #include "manager.h" +#include "manager-varlink.h" #include "mkdir-label.h" #include "strv.h" #include "unit.h" #include "user-util.h" #include "varlink.h" #include "varlink-internal.h" +#include "varlink-io.systemd.Manager.h" #include "varlink-io.systemd.ManagedOOM.h" #include "varlink-io.systemd.UserDatabase.h" #include "varlink-io.systemd.service.h" +#include "varlink-serialize.h" #include "varlink-util.h" typedef struct LookupParameters { @@ -593,35 +597,50 @@ int manager_setup_varlink_server(Manager *m) { if (m->varlink_server) return 0; - if (!MANAGER_IS_SYSTEM(m)) - return -EINVAL; + sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA; + if (MANAGER_IS_SYSTEM(m)) + flags |= SD_VARLINK_SERVER_ACCOUNT_UID; - r = varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA, m); + r = varlink_server_new(&s, flags, m); if (r < 0) return log_debug_errno(r, "Failed to allocate Varlink server: %m"); r = sd_varlink_server_add_interface_many( s, - &vl_interface_io_systemd_UserDatabase, - &vl_interface_io_systemd_ManagedOOM, + &vl_interface_io_systemd_Manager, &vl_interface_io_systemd_service); if (r < 0) return log_debug_errno(r, "Failed to add interfaces to varlink server: %m"); r = sd_varlink_server_bind_method_many( s, - "io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record, - "io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record, - "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships, - "io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", vl_method_subscribe_managed_oom_cgroups, + "io.systemd.Manager.Describe", vl_method_describe_manager, "io.systemd.service.Ping", varlink_method_ping, "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_debug_errno(r, "Failed to register varlink methods: %m"); - r = sd_varlink_server_bind_disconnect(s, vl_disconnect); - if (r < 0) - return log_debug_errno(r, "Failed to register varlink disconnect handler: %m"); + if (MANAGER_IS_SYSTEM(m)) { + r = sd_varlink_server_add_interface_many( + s, + &vl_interface_io_systemd_UserDatabase, + &vl_interface_io_systemd_ManagedOOM); + if (r < 0) + return log_debug_errno(r, "Failed to add interfaces to varlink server: %m"); + + r = sd_varlink_server_bind_method_many( + s, + "io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record, + "io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record, + "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships, + "io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", vl_method_subscribe_managed_oom_cgroups); + if (r < 0) + return log_debug_errno(r, "Failed to register varlink methods: %m"); + + r = sd_varlink_server_bind_disconnect(s, vl_disconnect); + if (r < 0) + return log_debug_errno(r, "Failed to register varlink disconnect handler: %m"); + } r = sd_varlink_server_attach_event(s, m->event, EVENT_PRIORITY_IPC); if (r < 0) @@ -645,24 +664,15 @@ static int manager_varlink_init_system(Manager *m) { bool fresh = r > 0; if (!MANAGER_IS_TEST_RUN(m)) { - (void) mkdir_label("/run/systemd/userdb", 0755); + FOREACH_STRING(address, + "/run/systemd/userdb/io.systemd.DynamicUser", + VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM, + "/run/systemd/io.systemd.Manager") { + /* We might have got sockets through deserialization. Do not bind to them twice. */ + if (!fresh && varlink_server_contains_socket(m->varlink_server, address)) + continue; - FOREACH_STRING(address, "/run/systemd/userdb/io.systemd.DynamicUser", VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM) { - if (!fresh) { - /* We might have got sockets through deserialization. Do not bind to them twice. */ - - bool found = false; - LIST_FOREACH(sockets, ss, m->varlink_server->sockets) - if (path_equal(ss->address, address)) { - found = true; - break; - } - - if (found) - continue; - } - - r = sd_varlink_server_listen_address(m->varlink_server, address, 0666); + r = sd_varlink_server_listen_address(m->varlink_server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755); if (r < 0) return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address); } @@ -672,6 +682,8 @@ static int manager_varlink_init_system(Manager *m) { } static int manager_varlink_init_user(Manager *m) { + int r; + assert(m); if (!MANAGER_IS_USER(m)) @@ -680,6 +692,26 @@ static int manager_varlink_init_user(Manager *m) { if (MANAGER_IS_TEST_RUN(m)) return 0; + r = manager_setup_varlink_server(m); + if (r < 0) + return log_error_errno(r, "Failed to set up varlink server: %m"); + bool fresh = r > 0; + + FOREACH_STRING(a, + "systemd/io.systemd.Manager") { + _cleanup_free_ char *address = NULL; + address = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], a); + if (!address) + return -ENOMEM; + /* We might have got sockets through deserialization. Do not bind to them twice. */ + if (!fresh && varlink_server_contains_socket(m->varlink_server, address)) + continue; + + r = sd_varlink_server_listen_address(m->varlink_server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755); + if (r < 0) + return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address); + } + return manager_varlink_managed_oom_connect(m); } diff --git a/src/shared/meson.build b/src/shared/meson.build index c25715c71d2..dfcbc136f7a 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -194,6 +194,7 @@ shared_sources = files( 'varlink-io.systemd.Machine.c', 'varlink-io.systemd.MachineImage.c', 'varlink-io.systemd.ManagedOOM.c', + 'varlink-io.systemd.Manager.c', 'varlink-io.systemd.MountFileSystem.c', 'varlink-io.systemd.NamespaceResource.c', 'varlink-io.systemd.Network.c', diff --git a/src/shared/varlink-io.systemd.Manager.c b/src/shared/varlink-io.systemd.Manager.c new file mode 100644 index 00000000000..bc6a6077460 --- /dev/null +++ b/src/shared/varlink-io.systemd.Manager.c @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "build.h" +#include "varlink-idl-common.h" +#include "varlink-io.systemd.Manager.h" + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + LogLevelStruct, + SD_VARLINK_FIELD_COMMENT("'console' target log level"), + SD_VARLINK_DEFINE_FIELD(console, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("'kmsg' target log level"), + SD_VARLINK_DEFINE_FIELD(kmsg, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("'syslog' target log level"), + SD_VARLINK_DEFINE_FIELD(syslog, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("'journal' target log level"), + SD_VARLINK_DEFINE_FIELD(journal, SD_VARLINK_STRING, 0)); + +/* The split between ManagerContext and ManagerRuntime follows the rule: + * - Context is what cannot change once configuration is loaded. You can think about context settings as constants. + * - Runtime is changable settings at runtime, in other words - variables. */ + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ManagerContext, + SD_VARLINK_FIELD_COMMENT("The version string of the running systemd instance"), + SD_VARLINK_DEFINE_FIELD(Version, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("A short ID string describing the architecture the systemd instance is running on"), + SD_VARLINK_DEFINE_FIELD(Architecture, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The features that have been enabled and disabled for this build"), + SD_VARLINK_DEFINE_FIELD(Features, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("An array of strings describing the taints applied to the running system"), + SD_VARLINK_DEFINE_FIELD(Taints, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The unit search path"), + SD_VARLINK_DEFINE_FIELD(UnitPath, SD_VARLINK_STRING, SD_VARLINK_ARRAY), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/latest/systemd-system.conf.html#ManagerEnvironment="), + SD_VARLINK_DEFINE_FIELD(Environment, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultStandardOutput="), + SD_VARLINK_DEFINE_FIELD(DefaultStandardOutput, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultStandardError="), + SD_VARLINK_DEFINE_FIELD(DefaultStandardError, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#ServiceWatchdogs="), + SD_VARLINK_DEFINE_FIELD(ServiceWatchdogs, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultTimerAccuracySec="), + SD_VARLINK_DEFINE_FIELD(DefaultTimerAccuracyUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultTimeoutStartSec="), + SD_VARLINK_DEFINE_FIELD(DefaultTimeoutStartUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultTimeoutStopSec="), + SD_VARLINK_DEFINE_FIELD(DefaultTimeoutStopUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultTimeoutAbortSec="), + SD_VARLINK_DEFINE_FIELD(DefaultTimeoutAbortUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultDeviceTimeoutSec="), + SD_VARLINK_DEFINE_FIELD(DefaultDeviceTimeoutUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultRestartSec="), + SD_VARLINK_DEFINE_FIELD(DefaultRestartUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultStartLimit="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(DefaultStartLimit, RateLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultCPUAccounting="), + SD_VARLINK_DEFINE_FIELD(DefaultCPUAccounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultBlockIOAccounting="), + SD_VARLINK_DEFINE_FIELD(DefaultBlockIOAccounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultIOAccounting="), + SD_VARLINK_DEFINE_FIELD(DefaultIOAccounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultIPAccounting="), + SD_VARLINK_DEFINE_FIELD(DefaultIPAccounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultMemoryAccounting="), + SD_VARLINK_DEFINE_FIELD(DefaultMemoryAccounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultTasksAccounting="), + SD_VARLINK_DEFINE_FIELD(DefaultTasksAccounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultLimitCPU="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(DefaultLimits, ResourceLimitTable, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultTasksMax="), + SD_VARLINK_DEFINE_FIELD(DefaultTasksMax, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultMemoryPressureThresholdUSec="), + SD_VARLINK_DEFINE_FIELD(DefaultMemoryPressureThresholdUSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultMemoryPressureWatch="), + SD_VARLINK_DEFINE_FIELD(DefaultMemoryPressureWatch, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#TimerSlackNSec="), + SD_VARLINK_DEFINE_FIELD(TimerSlackNSec, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultOOMPolicy="), + SD_VARLINK_DEFINE_FIELD(DefaultOOMPolicy, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultOOMScoreAdjust="), + SD_VARLINK_DEFINE_FIELD(DefaultOOMScoreAdjust, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#CtrlAltDelBurstAction="), + SD_VARLINK_DEFINE_FIELD(CtrlAltDelBurstAction, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ManagerRuntime, + SD_VARLINK_FIELD_COMMENT("A short ID string describing the virtualization technology the system runs in"), + SD_VARLINK_DEFINE_FIELD(Virtualization, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("A short ID string describing the confidential virtualization technology the system runs in"), + SD_VARLINK_DEFINE_FIELD(ConfidentialVirtualization, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The console on which systemd asks for confirmation when spawning processes"), + SD_VARLINK_DEFINE_FIELD(ConfirmSpawn, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the firmware first began execution"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(FirmwareTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the boot loader first began execution"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LoaderTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the kernel first began execution"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(KernelTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the initrd first began execution"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the initrd first began execution"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(UserspaceTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the system finished booting up"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(FinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager started uploading security policies to the kernel"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SecurityStartTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager finished uploading security policies to the kernel"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SecurityFinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager started executing generators"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(GeneratorsStartTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager finished executing generators"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(GeneratorsFinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager first started loading units"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(UnitsLoadStartTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager first finished loading units"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(UnitsLoadFinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager last started loading units"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(UnitsLoadTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager started uploading security policies to the kernel in the initrd"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDSecurityStartTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager finished uploading security policies to the kernel in the initrd"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDSecurityFinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager started executing generators in the initrd"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDGeneratorsStartTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager finished executing generators in the initrd"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDGeneratorsFinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager first started loading units in the initrd"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDUnitsLoadStartTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the manager first finished loading units in the initrd"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(InitRDUnitsLoadFinishTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The current show status of the manager"), + SD_VARLINK_DEFINE_FIELD(ShowStatus, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The current log level of the manager"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LogLevel, LogLevelStruct, 0), + SD_VARLINK_FIELD_COMMENT("The current log target of the manager"), + SD_VARLINK_DEFINE_FIELD(LogTarget, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The amount of unique unit names currently loaded"), + SD_VARLINK_DEFINE_FIELD(NNames, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("The amount of failed units"), + SD_VARLINK_DEFINE_FIELD(NFailedUnits, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("The amount of currently queued jobs"), + SD_VARLINK_DEFINE_FIELD(NJobs, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("The total amount of queued jobs"), + SD_VARLINK_DEFINE_FIELD(NInstalledJobs, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("The total amount of failed jobs"), + SD_VARLINK_DEFINE_FIELD(NFailedJobs, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("Boot progress as a floating point value between 0.0 and 1.0"), + SD_VARLINK_DEFINE_FIELD(Progress, SD_VARLINK_FLOAT, 0), + SD_VARLINK_FIELD_COMMENT("The manager environment variables"), + SD_VARLINK_DEFINE_FIELD(Environment, SD_VARLINK_STRING, SD_VARLINK_ARRAY), + SD_VARLINK_FIELD_COMMENT("The hardware watchdog device currently in use"), + SD_VARLINK_DEFINE_FIELD(WatchdogDevice, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Timestamp when the hardware watchdog was last pinged"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(WatchdogLastPingTimestamp, Timestamp, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Root of the control group hierarchy that the manager is running in"), + SD_VARLINK_DEFINE_FIELD(ControlGroup, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Current state of the system"), + SD_VARLINK_DEFINE_FIELD(SystemState, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Exit code of the manager"), + SD_VARLINK_DEFINE_FIELD(ExitCode, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#RuntimeWatchdogSec="), + SD_VARLINK_DEFINE_FIELD(RuntimeWatchdogUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#RuntimeWatchdogPreSec="), + SD_VARLINK_DEFINE_FIELD(RuntimeWatchdogPreUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#RuntimeWatchdogPreGovernor="), + SD_VARLINK_DEFINE_FIELD(RuntimeWatchdogPreGovernor, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#RebootWatchdogSec="), + SD_VARLINK_DEFINE_FIELD(RebootWatchdogUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#KExecWatchdogSec="), + SD_VARLINK_DEFINE_FIELD(KExecWatchdogUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Encodes how many soft-reboots were successfully completed"), + SD_VARLINK_DEFINE_FIELD(SoftRebootsCount, SD_VARLINK_INT, 0)); + +static SD_VARLINK_DEFINE_METHOD( + Describe, + SD_VARLINK_FIELD_COMMENT("Configuration of the manager"), + SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Context, ManagerContext, 0), + SD_VARLINK_FIELD_COMMENT("Runtime information of the manager"), + SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Runtime, ManagerRuntime, 0)); + +SD_VARLINK_DEFINE_INTERFACE( + io_systemd_Manager, + "io.systemd.Manager", + &vl_method_Describe, + &vl_type_ManagerContext, + &vl_type_ManagerRuntime, + &vl_type_Timestamp, + &vl_type_ResourceLimit, + &vl_type_ResourceLimitTable, + &vl_type_RateLimit, + &vl_type_LogLevelStruct); diff --git a/src/shared/varlink-io.systemd.Manager.h b/src/shared/varlink-io.systemd.Manager.h new file mode 100644 index 00000000000..ce411888f92 --- /dev/null +++ b/src/shared/varlink-io.systemd.Manager.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "sd-varlink-idl.h" + +extern const sd_varlink_interface vl_interface_io_systemd_Manager; From f08c13466100e0dc70897d6e08fbc0f2005174f6 Mon Sep 17 00:00:00 2001 From: Ivan Kruglov Date: Thu, 6 Mar 2025 08:38:37 -0800 Subject: [PATCH 8/8] tests: tests for io.systemd.manager.Describe --- src/test/test-varlink-idl.c | 3 +++ test/units/TEST-74-AUX-UTILS.varlinkctl.sh | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/test/test-varlink-idl.c b/src/test/test-varlink-idl.c index d3e4a6a116c..c2e8891edbe 100644 --- a/src/test/test-varlink-idl.c +++ b/src/test/test-varlink-idl.c @@ -19,6 +19,7 @@ #include "varlink-io.systemd.Login.h" #include "varlink-io.systemd.Machine.h" #include "varlink-io.systemd.MachineImage.h" +#include "varlink-io.systemd.Manager.h" #include "varlink-io.systemd.ManagedOOM.h" #include "varlink-io.systemd.MountFileSystem.h" #include "varlink-io.systemd.NamespaceResource.h" @@ -198,6 +199,8 @@ TEST(parse_format) { print_separator(); test_parse_format_one(&vl_interface_io_systemd_MachineImage); print_separator(); + test_parse_format_one(&vl_interface_io_systemd_Manager); + print_separator(); test_parse_format_one(&vl_interface_io_systemd_AskPassword); print_separator(); test_parse_format_one(&vl_interface_io_systemd_Udev); diff --git a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh index 921fadf998c..07b857e47db 100755 --- a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh +++ b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh @@ -166,3 +166,14 @@ varlinkctl call /run/systemd/io.systemd.Hostname io.systemd.Hostname.Describe '{ varlinkctl --exec call /run/systemd/io.systemd.Hostname io.systemd.Hostname.Describe '{}' -- jq > /tmp/describe2.json cmp /tmp/describe1.json /tmp/describe2.json rm /tmp/describe1.json /tmp/describe2.json + +# test io.systemd.Manager +varlinkctl info /run/systemd/io.systemd.Manager +varlinkctl introspect /run/systemd/io.systemd.Manager io.systemd.Manager +varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Manager.Describe '{}' + +# test io.systemd.Manager in user manager +systemctl start user@4711 +varlinkctl info /run/user/4711/systemd/io.systemd.Manager +varlinkctl introspect /run/user/4711/systemd/io.systemd.Manager +varlinkctl call /run/user/4711/systemd/io.systemd.Manager io.systemd.Manager.Describe '{}'